mirror of
https://github.com/igniterealtime/Spark.git
synced 2025-12-01 12:27:58 +00:00
reworked apple plugin
Unread Messages show as Dock-Badges like Mail does DockBouncing reenabled Added DockMenu (rightclick Dock) to do: add MacOSX MenuBar when using other Look&Feels Growl.plugin git-svn-id: http://svn.igniterealtime.org/svn/repos/spark/trunk@12224 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
committed by
wolf.posdorfer
parent
49e329ae99
commit
3de869edc6
@ -455,13 +455,13 @@ public final class MainWindow extends ChatFrame implements ActionListener {
|
||||
}
|
||||
});
|
||||
|
||||
if ((Spark.isWindows() || Spark.isLinux()) && !Default.getBoolean("DISABLE_EXIT")) {
|
||||
if ((Spark.isWindows() || Spark.isLinux()) || Spark.isMac() && !Default.getBoolean("DISABLE_EXIT")) {
|
||||
connectMenu.add(logoutMenuItem);
|
||||
connectMenu.add(logoutWithStatus);
|
||||
connectMenu.addSeparator();
|
||||
}
|
||||
|
||||
if (!Spark.isMac() && !Default.getBoolean("DISABLE_EXIT")) {
|
||||
if (!Default.getBoolean("DISABLE_EXIT")) {
|
||||
connectMenu.add(exitMenuItem);
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,10 @@
|
||||
*/
|
||||
package org.jivesoftware.sparkimpl.plugin.systray;
|
||||
|
||||
import java.awt.Menu;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.MouseInfo;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.Window;
|
||||
@ -236,6 +240,9 @@ public class SysTrayPlugin implements Plugin, NativeHandler,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
|
||||
|
||||
trayIcon = new TrayIcon(availableIcon.getImage(),
|
||||
Default.getString(Default.APPLICATION_NAME), null);
|
||||
trayIcon.setImageAutoSize(true);
|
||||
@ -244,8 +251,10 @@ public class SysTrayPlugin implements Plugin, NativeHandler,
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent event) {
|
||||
|
||||
if (event.getButton() == MouseEvent.BUTTON1
|
||||
&& event.getClickCount() == 1) {
|
||||
|
||||
|
||||
if (SparkManager.getMainWindow().isVisible()) {
|
||||
SparkManager.getMainWindow().setVisible(false);
|
||||
@ -257,9 +266,23 @@ public class SysTrayPlugin implements Plugin, NativeHandler,
|
||||
SparkManager.getMainWindow().toFront();
|
||||
// SparkManager.getMainWindow().requestFocus();
|
||||
} else if (event.getButton() == MouseEvent.BUTTON3) {
|
||||
popupMenu.setLocation(event.getX(), event.getY());
|
||||
popupMenu.setInvoker(popupMenu);
|
||||
popupMenu.setVisible(true);
|
||||
|
||||
if (popupMenu.isVisible()) {
|
||||
popupMenu.setVisible(false);
|
||||
} else {
|
||||
|
||||
double x = MouseInfo.getPointerInfo().getLocation().getX();
|
||||
double y = MouseInfo.getPointerInfo().getLocation().getY();
|
||||
|
||||
if (Spark.isMac()) {
|
||||
popupMenu.setLocation((int) x, (int) y);
|
||||
} else {
|
||||
popupMenu.setLocation(event.getX(), event.getY());
|
||||
}
|
||||
|
||||
popupMenu.setInvoker(popupMenu);
|
||||
popupMenu.setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,6 +299,15 @@ public class SysTrayPlugin implements Plugin, NativeHandler,
|
||||
@Override
|
||||
public void mousePressed(MouseEvent event) {
|
||||
|
||||
// on Mac i would want the window to show when i left-click the Icon
|
||||
if (Spark.isMac() && event.getButton()!=MouseEvent.BUTTON3) {
|
||||
SparkManager.getMainWindow().setVisible(false);
|
||||
SparkManager.getMainWindow().setVisible(true);
|
||||
SparkManager.getMainWindow().requestFocusInWindow();
|
||||
SparkManager.getMainWindow().bringFrameIntoFocus();
|
||||
SparkManager.getMainWindow().toFront();
|
||||
SparkManager.getMainWindow().requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,383 @@
|
||||
/**
|
||||
* $RCSfile: ,v $
|
||||
* $Revision: $
|
||||
* $Date: $
|
||||
*
|
||||
* Copyright (C) 2004-2010 Jive Software. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jivesoftware.spark.plugin.apple;
|
||||
|
||||
//import com.apple.cocoa.application.*;
|
||||
//import com.apple.cocoa.foundation.NSSelector;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import org.jivesoftware.resource.Res;
|
||||
import org.jivesoftware.smack.Roster;
|
||||
import org.jivesoftware.smack.RosterEntry;
|
||||
import org.jivesoftware.smack.RosterListener;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.spark.PresenceManager;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
import org.jivesoftware.spark.ui.PresenceListener;
|
||||
|
||||
import com.apple.eawt.Application;
|
||||
|
||||
/**
|
||||
* @author Wolf.Posdorfer
|
||||
*/
|
||||
public class AppleDock implements ActionListener, RosterListener, PresenceListener {
|
||||
//
|
||||
// private final NSMenu contactMenu;
|
||||
// private final Hashtable<String,NSMenuItem> entries;
|
||||
// private final NSStatusItem statusItem;
|
||||
// private final NSMenuItem freeToChatItem;
|
||||
// private final NSMenuItem availableItem;
|
||||
// private final NSMenuItem awayItem;
|
||||
// private final NSMenuItem extendedAwayItem;
|
||||
// private final NSMenuItem doNotDisturbItem;
|
||||
|
||||
// private final JMenuBar _contactMenu;
|
||||
|
||||
public AppleDock() {
|
||||
|
||||
Application app = new Application();
|
||||
|
||||
PopupMenu menu = new PopupMenu();
|
||||
|
||||
PopupMenu statusmenu = new PopupMenu(Res.getString("menuitem.status"));
|
||||
|
||||
for (Presence p : PresenceManager.getPresences()) {
|
||||
MenuItem dd = new MenuItem(p.getStatus());
|
||||
dd.addActionListener(this);
|
||||
statusmenu.add(dd);
|
||||
}
|
||||
|
||||
menu.add(statusmenu);
|
||||
|
||||
JFrame frame = SparkManager.getMainWindow();
|
||||
frame.add(menu);
|
||||
|
||||
// set dock menu
|
||||
app.setDockMenu(menu);
|
||||
|
||||
SparkManager.getSessionManager().addPresenceListener(this);
|
||||
|
||||
}
|
||||
|
||||
public void display() {
|
||||
// we'll rather use the standard SystemTray provided by Spark
|
||||
// statusItem.setEnabled(true);
|
||||
}
|
||||
|
||||
public void showBlackIcon() {
|
||||
// we'll rather use the standard SystemTray provided by Spark
|
||||
// statusItem.setImage(AppleUtils.getImage("/images/black-spark.gif"));
|
||||
}
|
||||
|
||||
public void showActiveIcon() {
|
||||
// we'll rather use the standard SystemTray provided by Spark
|
||||
// statusItem.setImage(AppleUtils.getImage("/images/spark-16x16.png"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when NEW entries are added.
|
||||
*
|
||||
* @param addresses
|
||||
* the addressss added.
|
||||
*/
|
||||
public void entriesAdded(final Collection addresses) {
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// Roster roster = SparkManager.getConnection().getRoster();
|
||||
// for (Object address : addresses) {
|
||||
// String jid = (String) address;
|
||||
// RosterEntry entry = roster.getEntry(jid);
|
||||
// addEntry(entry);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public void entriesUpdated(final Collection addresses) {
|
||||
}
|
||||
|
||||
public void entriesDeleted(final Collection addresses) {
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// Roster roster = SparkManager.getConnection().getRoster();
|
||||
// for (Object address : addresses) {
|
||||
// String jid = (String) address;
|
||||
// RosterEntry entry = roster.getEntry(jid);
|
||||
// removeEntry(entry);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public void presenceChanged(final String user) {
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// Roster roster = SparkManager.getConnection().getRoster();
|
||||
// Presence presence = roster.getPresence(user);
|
||||
//
|
||||
// if (Presence.Mode.away.equals(presence.getMode())) {
|
||||
// RosterEntry entry = roster.getEntry(user);
|
||||
// removeEntry(entry);
|
||||
// } else if (Presence.Mode.available.equals(presence.getMode())
|
||||
// || Presence.Mode.chat.equals(presence.getMode())) {
|
||||
// RosterEntry entry = roster.getEntry(user);
|
||||
// addEntry(entry);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public void presenceChanged(final Presence presence) {
|
||||
//
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// if (Presence.Mode.chat.equals(presence.getMode())) {
|
||||
// freeToChatItem.setState(NSCell.OnState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
//
|
||||
// }
|
||||
// else if (Presence.Mode.available.equals(presence.getMode())) {
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OnState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
//
|
||||
// }
|
||||
// else if (Presence.Mode.away.equals(presence.getMode())) {
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OnState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
// }
|
||||
// else if (Presence.Mode.xa.equals(presence.getMode())) {
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OnState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
// }
|
||||
// else if (Presence.Mode.dnd.equals(presence.getMode())) {
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OnState);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
public void createChatRoom(final String item) {
|
||||
//
|
||||
// Runnable runnable = new Runnable() {
|
||||
//
|
||||
// public void run() {
|
||||
//
|
||||
// String nickname = item.title();
|
||||
// String jid =
|
||||
// SparkManager.getUserManager().getJIDFromDisplayName(nickname);
|
||||
// if (jid != null) {
|
||||
// String bareJID = StringUtils.parseBareAddress(jid);
|
||||
// ChatManager chatManager = SparkManager.getChatManager();
|
||||
// ChatRoom chatRoom = chatManager.createChatRoom(bareJID, nickname,
|
||||
// nickname);
|
||||
// chatManager.getChatContainer().activateChatRoom(chatRoom);
|
||||
// ChatFrame frame = chatManager.getChatContainer().getChatFrame();
|
||||
// frame.setState(Frame.NORMAL);
|
||||
// frame.setVisible(true);
|
||||
// frame.toFront();
|
||||
// NSApplication.sharedApplication().activateIgnoringOtherApps(true);
|
||||
// }
|
||||
// else {
|
||||
// Log.error("Cannot create chat room, could not find jid for nickname "
|
||||
// + nickname);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// };
|
||||
//
|
||||
// SwingUtilities.invokeLater(runnable);
|
||||
}
|
||||
|
||||
public void handleStatusChange(final String item) {
|
||||
//
|
||||
// String status = item.title();
|
||||
//
|
||||
// if (freeToChatItem.title().equals(status)) {
|
||||
// freeToChatItem.setState(NSCell.OnState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
//
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// StatusItem si =
|
||||
// SparkManager.getWorkspace().getStatusBar().getStatusItem("Free To Chat");
|
||||
// SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// else if (availableItem.title().equals(status)) {
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OnState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
//
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// StatusItem si =
|
||||
// SparkManager.getWorkspace().getStatusBar().getStatusItem("Online");
|
||||
// SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// }
|
||||
// else if (awayItem.title().equals(status)) {
|
||||
//
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OnState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
//
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// StatusItem si =
|
||||
// SparkManager.getWorkspace().getStatusBar().getStatusItem("Away");
|
||||
// SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// else if (extendedAwayItem.title().equals(status)) {
|
||||
//
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OnState);
|
||||
// doNotDisturbItem.setState(NSCell.OffState);
|
||||
//
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// StatusItem si =
|
||||
// SparkManager.getWorkspace().getStatusBar().getStatusItem("Extended Away");
|
||||
// SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// else if (doNotDisturbItem.title().equals(status)) {
|
||||
//
|
||||
// freeToChatItem.setState(NSCell.OffState);
|
||||
// availableItem.setState(NSCell.OffState);
|
||||
// awayItem.setState(NSCell.OffState);
|
||||
// extendedAwayItem.setState(NSCell.OffState);
|
||||
// doNotDisturbItem.setState(NSCell.OnState);
|
||||
//
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// StatusItem si =
|
||||
// SparkManager.getWorkspace().getStatusBar().getStatusItem("Do Not Disturb");
|
||||
// SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
private void populateMenu(Roster roster) {
|
||||
//
|
||||
// NSMenuItem item = new NSMenuItem();
|
||||
// item.setTitle("Available Contacts");
|
||||
// item.setEnabled(false);
|
||||
// contactMenu.addItem(item);
|
||||
//
|
||||
// for (RosterEntry entry : roster.getEntries()) {
|
||||
// final Presence p = roster.getPresence(entry.getUser());
|
||||
// if (p.isAvailable()) {
|
||||
// addEntry(entry);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
private void addEntry(RosterEntry entry) {
|
||||
// if (entry == null) {
|
||||
// return;
|
||||
// }
|
||||
// String nickname = entry.getName();
|
||||
// if (nickname == null) {
|
||||
// nickname = entry.getUser();
|
||||
// }
|
||||
//
|
||||
// // if there isn't already an entry add it
|
||||
// if (!entries.contains(nickname)) {
|
||||
// NSMenuItem menuItem = new NSMenuItem();
|
||||
// menuItem.setIndentationLevel(2);
|
||||
// menuItem.setEnabled(true);
|
||||
// menuItem.setTitle(nickname);
|
||||
// menuItem.setAction(new NSSelector("createChatRoom", new
|
||||
// Class[]{NSMenuItem.class}));
|
||||
// menuItem.setTarget(this);
|
||||
// contactMenu.addItem(menuItem);
|
||||
// entries.put(nickname, menuItem);
|
||||
// }
|
||||
}
|
||||
|
||||
private void removeEntry(RosterEntry entry) {
|
||||
// if (entry == null) {
|
||||
// return;
|
||||
// }
|
||||
// String nickname = entry.getName();
|
||||
// NSMenuItem menuItem = entries.remove(nickname);
|
||||
// if (menuItem != null) {
|
||||
// contactMenu.removeItem(menuItem);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
Presence presence = null;
|
||||
for (Presence p : PresenceManager.getPresences()) {
|
||||
if (p.getStatus().equals(e.getActionCommand())) {
|
||||
presence = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SparkManager.getSessionManager().changePresence(presence);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -42,6 +42,7 @@ import org.jivesoftware.spark.plugin.Plugin;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Frame;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.*;
|
||||
import java.util.Timer;
|
||||
@ -49,20 +50,21 @@ import java.util.TimerTask;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* Plugins for handling Mac OS X specific functionality
|
||||
*
|
||||
* @author Andrew Wright
|
||||
* Plugins for handling Mac OS X specific functionality supports 10.6+
|
||||
*
|
||||
* @author Wolf Posdorfer
|
||||
*/
|
||||
public class ApplePlugin implements Plugin, NativeHandler {
|
||||
|
||||
private AppleStatusMenu statusMenu;
|
||||
private AppleUtils appleUtils;
|
||||
private AppleDock _appledock;
|
||||
private AppleUtils _appleUtils;
|
||||
private boolean unavailable;
|
||||
private int previousPriority;
|
||||
private boolean addedFrameListener;
|
||||
@ -70,297 +72,308 @@ public class ApplePlugin implements Plugin, NativeHandler {
|
||||
|
||||
private ChatFrame chatFrame;
|
||||
|
||||
private Application _application;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void initialize() {
|
||||
if (Spark.isMac()) {
|
||||
appleUtils = new AppleUtils();
|
||||
SparkManager.getNativeManager().addNativeHandler(this);
|
||||
if (Spark.isMac()) {
|
||||
|
||||
|
||||
_appleUtils = new AppleUtils();
|
||||
_appledock = new AppleDock();
|
||||
|
||||
handleIdle();
|
||||
SparkManager.getNativeManager().addNativeHandler(this);
|
||||
|
||||
// Remove the About Menu Item from the help menu
|
||||
MainWindow mainWindow = SparkManager.getMainWindow();
|
||||
handleIdle();
|
||||
|
||||
JMenu helpMenu = mainWindow.getMenuByName("Help");
|
||||
Component[] menuComponents = helpMenu.getMenuComponents();
|
||||
Component prev = null;
|
||||
for (Component current : menuComponents) {
|
||||
if (current instanceof JMenuItem) {
|
||||
JMenuItem item = (JMenuItem) current;
|
||||
if ("About".equals(item.getText())) {
|
||||
helpMenu.remove(item);
|
||||
// // register an application listener to show the about box
|
||||
_application = Application.getApplication();
|
||||
|
||||
// We want to remove the seperator
|
||||
if (prev != null && (prev instanceof JSeparator)) {
|
||||
helpMenu.remove(prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = current;
|
||||
}
|
||||
_application.setEnabledPreferencesMenu(true);
|
||||
_application.addPreferencesMenuItem();
|
||||
_application.addApplicationListener(new ApplicationAdapter() {
|
||||
|
||||
JMenu connectMenu = mainWindow.getMenuByName("Spark");
|
||||
connectMenu.setText("Connect");
|
||||
menuComponents = connectMenu.getMenuComponents();
|
||||
JSeparator lastSeperator = null;
|
||||
for (Component current : menuComponents) {
|
||||
if (current instanceof JMenuItem) {
|
||||
JMenuItem item = (JMenuItem) current;
|
||||
public void handlePreferences(ApplicationEvent applicationEvent) {
|
||||
SparkManager.getPreferenceManager().showPreferences();
|
||||
}
|
||||
|
||||
if ("Preferences".equals(item.getText())) {
|
||||
connectMenu.remove(item);
|
||||
} else if ("Log Out".equals(item.getText())) {
|
||||
connectMenu.remove(item);
|
||||
}
|
||||
public void handleReOpenApplication(ApplicationEvent event) {
|
||||
MainWindow mainWindow = SparkManager.getMainWindow();
|
||||
if (!mainWindow.isVisible()) {
|
||||
mainWindow.setState(Frame.NORMAL);
|
||||
mainWindow.setVisible(true);
|
||||
}
|
||||
|
||||
if (SparkManager.getChatManager().getChatContainer()
|
||||
.getTotalNumberOfUnreadMessages() > 0) {
|
||||
final ChatFrame frame = SparkManager.getChatManager().getChatContainer()
|
||||
.getChatFrame();
|
||||
frame.setState(Frame.NORMAL);
|
||||
frame.setVisible(true);
|
||||
frame.toFront();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (current instanceof JSeparator) {
|
||||
lastSeperator = (JSeparator) current;
|
||||
}
|
||||
}
|
||||
if (lastSeperator != null) {
|
||||
connectMenu.remove(lastSeperator);
|
||||
}
|
||||
public void handleQuit(ApplicationEvent applicationEvent) {
|
||||
SparkManager.getMainWindow().shutdown();
|
||||
}
|
||||
|
||||
// register an application listener to show the about box
|
||||
Application application = Application.getApplication();
|
||||
});
|
||||
|
||||
application.setEnabledPreferencesMenu(true);
|
||||
application.addPreferencesMenuItem();
|
||||
application.addApplicationListener(new ApplicationAdapter() {
|
||||
// Create Mac MenuBar when not in system.laf
|
||||
createMenuBarEntries();
|
||||
|
||||
public void handlePreferences(ApplicationEvent applicationEvent) {
|
||||
SparkManager.getPreferenceManager().showPreferences();
|
||||
}
|
||||
|
||||
public void handleReOpenApplication(ApplicationEvent event) {
|
||||
MainWindow mainWindow = SparkManager.getMainWindow();
|
||||
if (!mainWindow.isVisible()) {
|
||||
mainWindow.setState(Frame.NORMAL);
|
||||
mainWindow.setVisible(true);
|
||||
}
|
||||
|
||||
if(SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages() > 0){
|
||||
final ChatFrame frame = SparkManager.getChatManager().getChatContainer().getChatFrame();
|
||||
frame.setState(Frame.NORMAL);
|
||||
frame.setVisible(true);
|
||||
frame.toFront();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void handleQuit(ApplicationEvent applicationEvent) {
|
||||
SparkManager.getMainWindow().shutdown();
|
||||
}
|
||||
|
||||
});
|
||||
statusMenu = new AppleStatusMenu();
|
||||
statusMenu.display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (Spark.isMac()) {
|
||||
SparkManager.getNativeManager().removeNativeHandler(this);
|
||||
}
|
||||
if (Spark.isMac()) {
|
||||
SparkManager.getNativeManager().removeNativeHandler(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canShutDown() {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void uninstall() {
|
||||
// No need, since this is internal
|
||||
// No need, since this is internal
|
||||
}
|
||||
|
||||
public void flashWindow(Window window) {
|
||||
appleUtils.bounceDockIcon(true);
|
||||
statusMenu.showActiveIcon();
|
||||
_appleUtils.bounceDockIcon(true);
|
||||
// statusMenu.showActiveIcon();
|
||||
}
|
||||
|
||||
public void flashWindowStopWhenFocused(Window window) {
|
||||
appleUtils.bounceDockIcon(true);
|
||||
try {
|
||||
statusMenu.showActiveIcon();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Log.error(e);
|
||||
}
|
||||
_appleUtils.bounceDockIcon(true);
|
||||
// statusMenu.showActiveIcon();
|
||||
|
||||
}
|
||||
|
||||
public void stopFlashing(Window window) {
|
||||
appleUtils.resetDock();
|
||||
try {
|
||||
statusMenu.showBlackIcon();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Log.error(e);
|
||||
}
|
||||
_appleUtils.resetDock();
|
||||
// try {
|
||||
// statusMenu.showBlackIcon();
|
||||
// } catch (Exception e) {
|
||||
// Log.error(e);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
public boolean handleNotification() {
|
||||
return Spark.isMac();
|
||||
return Spark.isMac();
|
||||
}
|
||||
|
||||
private void handleIdle() {
|
||||
SparkManager.getMainWindow().addComponentListener(new ComponentListener() {
|
||||
public void componentResized(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
SparkManager.getMainWindow().addComponentListener(new ComponentListener() {
|
||||
public void componentResized(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
|
||||
public void componentMoved(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
public void componentMoved(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
|
||||
public void componentShown(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
public void componentShown(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
|
||||
public void componentHidden(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
});
|
||||
public void componentHidden(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
});
|
||||
|
||||
SparkManager.getChatManager().addChatRoomListener(new ChatRoomListenerAdapter() {
|
||||
public void chatRoomOpened(ChatRoom room) {
|
||||
if (!addedFrameListener) {
|
||||
chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame();
|
||||
chatFrame.addComponentListener(new ComponentListener() {
|
||||
public void componentResized(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
SparkManager.getChatManager().addChatRoomListener(new ChatRoomListenerAdapter() {
|
||||
public void chatRoomOpened(ChatRoom room) {
|
||||
if (!addedFrameListener) {
|
||||
chatFrame = SparkManager.getChatManager().getChatContainer().getChatFrame();
|
||||
chatFrame.addComponentListener(new ComponentListener() {
|
||||
public void componentResized(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
|
||||
public void componentMoved(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
public void componentMoved(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
|
||||
public void componentShown(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
public void componentShown(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
|
||||
public void componentHidden(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
});
|
||||
public void componentHidden(ComponentEvent componentEvent) {
|
||||
setActivity();
|
||||
}
|
||||
});
|
||||
|
||||
addedFrameListener = true;
|
||||
addedFrameListener = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
setActivity();
|
||||
}
|
||||
setActivity();
|
||||
}
|
||||
|
||||
public void chatRoomClosed(ChatRoom room) {
|
||||
setActivity();
|
||||
}
|
||||
});
|
||||
|
||||
public void chatRoomClosed(ChatRoom room) {
|
||||
setActivity();
|
||||
}
|
||||
});
|
||||
SparkManager.getSessionManager().addPresenceListener(new PresenceListener() {
|
||||
public void presenceChanged(Presence presence) {
|
||||
if (presence.isAvailable() && !presence.isAway()) {
|
||||
lastActive = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SparkManager.getSessionManager().addPresenceListener(new PresenceListener() {
|
||||
public void presenceChanged(Presence presence) {
|
||||
if(presence.isAvailable() && !presence.isAway()){
|
||||
lastActive = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
});
|
||||
final Timer timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
sparkIsIdle();
|
||||
}
|
||||
}, 10000, 10000);
|
||||
|
||||
|
||||
final Timer timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
sparkIsIdle();
|
||||
}
|
||||
}, 10000, 10000);
|
||||
|
||||
lastActive = System.currentTimeMillis();
|
||||
lastActive = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
|
||||
public void setActivity() {
|
||||
lastActive = System.currentTimeMillis();
|
||||
setAvailableIfActive();
|
||||
lastActive = System.currentTimeMillis();
|
||||
setAvailableIfActive();
|
||||
}
|
||||
|
||||
|
||||
private void sparkIsIdle() {
|
||||
LocalPreferences localPref = SettingsManager.getLocalPreferences();
|
||||
if (!localPref.isIdleOn()) {
|
||||
return;
|
||||
}
|
||||
LocalPreferences localPref = SettingsManager.getLocalPreferences();
|
||||
if (!localPref.isIdleOn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Handle if spark is not connected to the server.
|
||||
if (SparkManager.getConnection() == null || !SparkManager.getConnection().isConnected()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Handle if spark is not connected to the server.
|
||||
if (SparkManager.getConnection() == null || !SparkManager.getConnection().isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Change Status
|
||||
Workspace workspace = SparkManager.getWorkspace();
|
||||
if (workspace != null) {
|
||||
Presence presence = workspace.getStatusBar().getPresence();
|
||||
long diff = System.currentTimeMillis() - lastActive;
|
||||
boolean idle = diff > 60000 * 60;
|
||||
if (presence.getMode() == Presence.Mode.available && idle) {
|
||||
unavailable = true;
|
||||
StatusItem away = workspace.getStatusBar().getStatusItem("Away");
|
||||
Presence p = away.getPresence();
|
||||
p.setStatus(Res.getString("message.away.idle"));
|
||||
// Change Status
|
||||
Workspace workspace = SparkManager.getWorkspace();
|
||||
if (workspace != null) {
|
||||
Presence presence = workspace.getStatusBar().getPresence();
|
||||
long diff = System.currentTimeMillis() - lastActive;
|
||||
boolean idle = diff > 60000 * 60;
|
||||
if (presence.getMode() == Presence.Mode.available && idle) {
|
||||
unavailable = true;
|
||||
StatusItem away = workspace.getStatusBar().getStatusItem("Away");
|
||||
Presence p = away.getPresence();
|
||||
p.setStatus(Res.getString("message.away.idle"));
|
||||
|
||||
previousPriority = presence.getPriority();
|
||||
previousPriority = presence.getPriority();
|
||||
|
||||
p.setPriority(0);
|
||||
p.setPriority(0);
|
||||
|
||||
SparkManager.getSessionManager().changePresence(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Log.error("Error with IDLE status.", e);
|
||||
}
|
||||
SparkManager.getSessionManager().changePresence(p);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.error("Error with IDLE status.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setAvailableIfActive() {
|
||||
if (!unavailable) {
|
||||
return;
|
||||
}
|
||||
// Handle if spark is not connected to the server.
|
||||
if (SparkManager.getConnection() == null || !SparkManager.getConnection().isConnected()) {
|
||||
return;
|
||||
}
|
||||
if (!unavailable) {
|
||||
return;
|
||||
}
|
||||
// Handle if spark is not connected to the server.
|
||||
if (SparkManager.getConnection() == null || !SparkManager.getConnection().isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Change Status
|
||||
Workspace workspace = SparkManager.getWorkspace();
|
||||
if (workspace != null) {
|
||||
Presence presence = workspace.getStatusBar().getStatusItem(Res.getString("available")).getPresence();
|
||||
if (previousPriority != -1) {
|
||||
presence.setPriority(previousPriority);
|
||||
}
|
||||
// Change Status
|
||||
Workspace workspace = SparkManager.getWorkspace();
|
||||
if (workspace != null) {
|
||||
Presence presence = workspace.getStatusBar().getStatusItem(Res.getString("available"))
|
||||
.getPresence();
|
||||
if (previousPriority != -1) {
|
||||
presence.setPriority(previousPriority);
|
||||
}
|
||||
|
||||
SparkManager.getSessionManager().changePresence(presence);
|
||||
unavailable = false;
|
||||
lastActive = System.currentTimeMillis();
|
||||
}
|
||||
SparkManager.getSessionManager().changePresence(presence);
|
||||
unavailable = false;
|
||||
lastActive = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean openFile(File file) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean launchEmailClient(String to, String subject) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean launchBrowser(String url) {
|
||||
try {
|
||||
BrowserLauncher.openURL(url);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Log.error(e);
|
||||
}
|
||||
return true;
|
||||
try {
|
||||
BrowserLauncher.openURL(url);
|
||||
} catch (IOException e) {
|
||||
Log.error(e);
|
||||
} catch (Exception e) {
|
||||
Log.error(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Mac Specific MenuBar entries When not using the system look and
|
||||
* feel
|
||||
*/
|
||||
private void createMenuBarEntries() {
|
||||
|
||||
String curlaf = UIManager.getLookAndFeel().getName();
|
||||
|
||||
if (!curlaf.equals("Mac OS X")) {
|
||||
_application.setDefaultMenuBar(SparkManager.getMainWindow().getMenu());
|
||||
}
|
||||
|
||||
// MainWindow mainWindow = SparkManager.getMainWindow();
|
||||
//
|
||||
// JMenu helpMenu = mainWindow.getMenuByName("Help");
|
||||
// Component[] menuComponents = helpMenu.getMenuComponents();
|
||||
// Component prev = null;
|
||||
// for (Component current : menuComponents) {
|
||||
// if (current instanceof JMenuItem) {
|
||||
// JMenuItem item = (JMenuItem) current;
|
||||
// if ("About".equals(item.getText())) {
|
||||
// helpMenu.remove(item);
|
||||
//
|
||||
// // We want to remove the seperator
|
||||
// if (prev != null && (prev instanceof JSeparator)) {
|
||||
// helpMenu.remove(prev);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// prev = current;
|
||||
// }
|
||||
//
|
||||
// JMenu connectMenu = mainWindow.getMenuByName("Spark");
|
||||
// connectMenu.setText("Connect");
|
||||
// menuComponents = connectMenu.getMenuComponents();
|
||||
// JSeparator lastSeperator = null;
|
||||
// for (Component current : menuComponents) {
|
||||
// if (current instanceof JMenuItem) {
|
||||
// JMenuItem item = (JMenuItem) current;
|
||||
//
|
||||
// if ("Preferences".equals(item.getText())) {
|
||||
// connectMenu.remove(item);
|
||||
// } else if ("Log Out".equals(item.getText())) {
|
||||
// connectMenu.remove(item);
|
||||
// }
|
||||
//
|
||||
// } else if (current instanceof JSeparator) {
|
||||
// lastSeperator = (JSeparator) current;
|
||||
// }
|
||||
// }
|
||||
// if (lastSeperator != null) {
|
||||
// connectMenu.remove(lastSeperator);
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,443 +0,0 @@
|
||||
/**
|
||||
* $RCSfile: ,v $
|
||||
* $Revision: $
|
||||
* $Date: $
|
||||
*
|
||||
* Copyright (C) 2004-2010 Jive Software. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jivesoftware.spark.plugin.apple;
|
||||
|
||||
import com.apple.cocoa.application.*;
|
||||
import com.apple.cocoa.foundation.NSSelector;
|
||||
import org.jivesoftware.smack.Roster;
|
||||
import org.jivesoftware.smack.RosterEntry;
|
||||
import org.jivesoftware.smack.RosterListener;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.spark.ChatManager;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
import org.jivesoftware.spark.Workspace;
|
||||
import org.jivesoftware.spark.ui.ChatFrame;
|
||||
import org.jivesoftware.spark.ui.ChatRoom;
|
||||
import org.jivesoftware.spark.ui.PresenceListener;
|
||||
import org.jivesoftware.spark.ui.status.StatusItem;
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* @author Andrew Wright
|
||||
*/
|
||||
public class AppleStatusMenu implements RosterListener, PresenceListener {
|
||||
|
||||
private final NSMenu contactMenu;
|
||||
private final Hashtable<String,NSMenuItem> entries;
|
||||
private final NSStatusItem statusItem;
|
||||
private final NSMenuItem freeToChatItem;
|
||||
private final NSMenuItem availableItem;
|
||||
private final NSMenuItem awayItem;
|
||||
private final NSMenuItem extendedAwayItem;
|
||||
private final NSMenuItem doNotDisturbItem;
|
||||
|
||||
|
||||
public AppleStatusMenu() {
|
||||
entries = new Hashtable<String,NSMenuItem>();
|
||||
|
||||
Roster roster = SparkManager.getConnection().getRoster();
|
||||
roster.addRosterListener(this);
|
||||
|
||||
this.contactMenu = new NSMenu();
|
||||
|
||||
NSMenuItem item = new NSMenuItem();
|
||||
item.setTitle("My Status:");
|
||||
item.setEnabled(false);
|
||||
contactMenu.addItem(item);
|
||||
|
||||
freeToChatItem = new NSMenuItem();
|
||||
freeToChatItem.setEnabled(true);
|
||||
freeToChatItem.setTitle("Free To Chat");
|
||||
freeToChatItem.setTarget(this);
|
||||
freeToChatItem.setAction(new NSSelector("handleStatusChange", new Class[]{NSMenuItem.class}));
|
||||
freeToChatItem.setImage(AppleUtils.getImage("/images/im_free_chat.png"));
|
||||
contactMenu.addItem(freeToChatItem);
|
||||
|
||||
availableItem = new NSMenuItem();
|
||||
availableItem.setEnabled(true);
|
||||
availableItem.setTitle("Available");
|
||||
availableItem.setTarget(this);
|
||||
availableItem.setAction(new NSSelector("handleStatusChange", new Class[]{NSMenuItem.class}));
|
||||
availableItem.setImage(AppleUtils.getImage("/images/green-ball.png"));
|
||||
contactMenu.addItem(availableItem);
|
||||
|
||||
awayItem = new NSMenuItem();
|
||||
awayItem.setEnabled(true);
|
||||
awayItem.setTitle("Away");
|
||||
awayItem.setTarget(this);
|
||||
awayItem.setAction(new NSSelector("handleStatusChange", new Class[]{NSMenuItem.class}));
|
||||
awayItem.setImage(AppleUtils.getImage("/images/im_away.png"));
|
||||
contactMenu.addItem(awayItem);
|
||||
|
||||
extendedAwayItem = new NSMenuItem();
|
||||
extendedAwayItem.setEnabled(true);
|
||||
extendedAwayItem.setTitle("Extended Away");
|
||||
extendedAwayItem.setTarget(this);
|
||||
extendedAwayItem.setAction(new NSSelector("handleStatusChange", new Class[]{NSMenuItem.class}));
|
||||
extendedAwayItem.setImage(AppleUtils.getImage("/images/im_away.png"));
|
||||
contactMenu.addItem(extendedAwayItem);
|
||||
|
||||
doNotDisturbItem = new NSMenuItem();
|
||||
doNotDisturbItem.setEnabled(true);
|
||||
doNotDisturbItem.setTitle("Do Not Disturb");
|
||||
doNotDisturbItem.setTarget(this);
|
||||
doNotDisturbItem.setAction(new NSSelector("handleStatusChange", new Class[]{NSMenuItem.class}));
|
||||
doNotDisturbItem.setImage(AppleUtils.getImage("/images/im_dnd.png"));
|
||||
contactMenu.addItem(doNotDisturbItem);
|
||||
|
||||
Workspace workspace = SparkManager.getWorkspace();
|
||||
if (workspace != null) {
|
||||
Presence presence = workspace.getStatusBar().getPresence();
|
||||
if (Presence.Mode.chat.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OnState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
}
|
||||
else if (Presence.Mode.available.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OnState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
}
|
||||
else if (Presence.Mode.away.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OnState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
}
|
||||
else if (Presence.Mode.xa.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OnState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
}
|
||||
else if (Presence.Mode.dnd.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OnState);
|
||||
}
|
||||
}
|
||||
contactMenu.addItem(item.separatorItem());
|
||||
|
||||
|
||||
populateMenu(roster);
|
||||
|
||||
NSStatusBar bar = NSStatusBar.systemStatusBar();
|
||||
statusItem = bar.statusItem(NSStatusBar.VariableStatusItemLength);
|
||||
statusItem.setImage(AppleUtils.getImage("/images/black-spark.gif"));
|
||||
statusItem.setHighlightMode(true);
|
||||
statusItem.setMenu(contactMenu);
|
||||
statusItem.setEnabled(false);
|
||||
|
||||
SparkManager.getSessionManager().addPresenceListener(this);
|
||||
|
||||
}
|
||||
|
||||
public void display() {
|
||||
statusItem.setEnabled(true);
|
||||
}
|
||||
|
||||
public void showBlackIcon() {
|
||||
statusItem.setImage(AppleUtils.getImage("/images/black-spark.gif"));
|
||||
}
|
||||
|
||||
public void showActiveIcon() {
|
||||
statusItem.setImage(AppleUtils.getImage("/images/spark-16x16.png"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when NEW entries are added.
|
||||
*
|
||||
* @param addresses the addressss added.
|
||||
*/
|
||||
public void entriesAdded(final Collection addresses) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
Roster roster = SparkManager.getConnection().getRoster();
|
||||
for (Object address : addresses) {
|
||||
String jid = (String) address;
|
||||
RosterEntry entry = roster.getEntry(jid);
|
||||
addEntry(entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void entriesUpdated(final Collection addresses) {
|
||||
}
|
||||
|
||||
public void entriesDeleted(final Collection addresses) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
Roster roster = SparkManager.getConnection().getRoster();
|
||||
for (Object address : addresses) {
|
||||
String jid = (String) address;
|
||||
RosterEntry entry = roster.getEntry(jid);
|
||||
removeEntry(entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void presenceChanged(final String user) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
Roster roster = SparkManager.getConnection().getRoster();
|
||||
Presence presence = roster.getPresence(user);
|
||||
|
||||
|
||||
if (Presence.Mode.away.equals(presence.getMode())) {
|
||||
RosterEntry entry = roster.getEntry(user);
|
||||
removeEntry(entry);
|
||||
}
|
||||
else if (Presence.Mode.available.equals(presence.getMode()) ||
|
||||
Presence.Mode.chat.equals(presence.getMode())) {
|
||||
RosterEntry entry = roster.getEntry(user);
|
||||
addEntry(entry);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void presenceChanged(final Presence presence) {
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (Presence.Mode.chat.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OnState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
}
|
||||
else if (Presence.Mode.available.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OnState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
}
|
||||
else if (Presence.Mode.away.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OnState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
}
|
||||
else if (Presence.Mode.xa.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OnState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
}
|
||||
else if (Presence.Mode.dnd.equals(presence.getMode())) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OnState);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void createChatRoom(final NSMenuItem item) {
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
|
||||
public void run() {
|
||||
|
||||
String nickname = item.title();
|
||||
String jid = SparkManager.getUserManager().getJIDFromDisplayName(nickname);
|
||||
if (jid != null) {
|
||||
String bareJID = StringUtils.parseBareAddress(jid);
|
||||
ChatManager chatManager = SparkManager.getChatManager();
|
||||
ChatRoom chatRoom = chatManager.createChatRoom(bareJID, nickname, nickname);
|
||||
chatManager.getChatContainer().activateChatRoom(chatRoom);
|
||||
ChatFrame frame = chatManager.getChatContainer().getChatFrame();
|
||||
frame.setState(Frame.NORMAL);
|
||||
frame.setVisible(true);
|
||||
frame.toFront();
|
||||
NSApplication.sharedApplication().activateIgnoringOtherApps(true);
|
||||
}
|
||||
else {
|
||||
Log.error("Cannot create chat room, could not find jid for nickname " + nickname);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
SwingUtilities.invokeLater(runnable);
|
||||
}
|
||||
|
||||
public void handleStatusChange(final NSMenuItem item) {
|
||||
|
||||
String status = item.title();
|
||||
|
||||
if (freeToChatItem.title().equals(status)) {
|
||||
freeToChatItem.setState(NSCell.OnState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
StatusItem si = SparkManager.getWorkspace().getStatusBar().getStatusItem("Free To Chat");
|
||||
SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (availableItem.title().equals(status)) {
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OnState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
StatusItem si = SparkManager.getWorkspace().getStatusBar().getStatusItem("Online");
|
||||
SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
else if (awayItem.title().equals(status)) {
|
||||
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OnState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
StatusItem si = SparkManager.getWorkspace().getStatusBar().getStatusItem("Away");
|
||||
SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (extendedAwayItem.title().equals(status)) {
|
||||
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OnState);
|
||||
doNotDisturbItem.setState(NSCell.OffState);
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
StatusItem si = SparkManager.getWorkspace().getStatusBar().getStatusItem("Extended Away");
|
||||
SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (doNotDisturbItem.title().equals(status)) {
|
||||
|
||||
freeToChatItem.setState(NSCell.OffState);
|
||||
availableItem.setState(NSCell.OffState);
|
||||
awayItem.setState(NSCell.OffState);
|
||||
extendedAwayItem.setState(NSCell.OffState);
|
||||
doNotDisturbItem.setState(NSCell.OnState);
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
StatusItem si = SparkManager.getWorkspace().getStatusBar().getStatusItem("Do Not Disturb");
|
||||
SparkManager.getSessionManager().changePresence(si.getPresence());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void populateMenu(Roster roster) {
|
||||
|
||||
NSMenuItem item = new NSMenuItem();
|
||||
item.setTitle("Available Contacts");
|
||||
item.setEnabled(false);
|
||||
contactMenu.addItem(item);
|
||||
|
||||
for (RosterEntry entry : roster.getEntries()) {
|
||||
final Presence p = roster.getPresence(entry.getUser());
|
||||
if (p.isAvailable()) {
|
||||
addEntry(entry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addEntry(RosterEntry entry) {
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
String nickname = entry.getName();
|
||||
if (nickname == null) {
|
||||
nickname = entry.getUser();
|
||||
}
|
||||
|
||||
// if there isn't already an entry add it
|
||||
if (!entries.contains(nickname)) {
|
||||
NSMenuItem menuItem = new NSMenuItem();
|
||||
menuItem.setIndentationLevel(2);
|
||||
menuItem.setEnabled(true);
|
||||
menuItem.setTitle(nickname);
|
||||
menuItem.setAction(new NSSelector("createChatRoom", new Class[]{NSMenuItem.class}));
|
||||
menuItem.setTarget(this);
|
||||
contactMenu.addItem(menuItem);
|
||||
entries.put(nickname, menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeEntry(RosterEntry entry) {
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
String nickname = entry.getName();
|
||||
NSMenuItem menuItem = entries.remove(nickname);
|
||||
if (menuItem != null) {
|
||||
contactMenu.removeItem(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -19,220 +19,121 @@
|
||||
*/
|
||||
package com.jivesoftware.spark.plugin.apple;
|
||||
|
||||
import com.apple.cocoa.application.NSApplication;
|
||||
import com.apple.cocoa.application.NSImage;
|
||||
import com.apple.cocoa.foundation.NSData;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
import com.apple.eawt.Application;
|
||||
|
||||
/**
|
||||
* Utilities for dealing with the apple dock
|
||||
*
|
||||
* @author Andrew Wright
|
||||
*
|
||||
* @author Wolf.Posdorfer
|
||||
*/
|
||||
public final class AppleUtils {
|
||||
|
||||
private boolean _flash;
|
||||
final Application _app;
|
||||
private boolean _usingDefaultIcon;
|
||||
|
||||
private boolean flash;
|
||||
private boolean usingDefaultIcon = true;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public AppleUtils() {
|
||||
_app = new Application();
|
||||
|
||||
final Thread iconThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
while (true) {
|
||||
if (!flash) {
|
||||
if (!usingDefaultIcon) {
|
||||
// Set default icon
|
||||
NSImage defaultImage = getDefaultImage();
|
||||
NSApplication.sharedApplication().setApplicationIconImage(defaultImage);
|
||||
usingDefaultIcon = true;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Log.error(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final NSImage image = getImageForMessageCountOn();
|
||||
final Thread iconThread = new Thread(new Runnable() {
|
||||
|
||||
NSApplication.sharedApplication().setApplicationIconImage(image);
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// Nothing to do
|
||||
}
|
||||
final NSImage image2 = getImageForMessageCountOff();
|
||||
NSApplication.sharedApplication().setApplicationIconImage(image2);
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// Nothing to do
|
||||
}
|
||||
public void run() {
|
||||
while (true) {
|
||||
if (!_flash) {
|
||||
setDockBadge(_app, getMessageCount());
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
Log.error(e);
|
||||
}
|
||||
} else {
|
||||
|
||||
usingDefaultIcon = false;
|
||||
}
|
||||
setDockBadge(_app, getMessageCount());
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
// Nothing to do
|
||||
}
|
||||
setDockBadge(_app, getMessageCount());
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
_usingDefaultIcon = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
iconThread.start();
|
||||
iconThread.start();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Flashing to false
|
||||
*/
|
||||
public void resetDock() {
|
||||
if (_flash) {
|
||||
_flash = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String of the current unread message count
|
||||
*
|
||||
* @return String like "10"
|
||||
*/
|
||||
public static String getMessageCount() {
|
||||
int no = SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages();
|
||||
|
||||
if (no > 999)
|
||||
no = 999;
|
||||
if (no == 0) {
|
||||
return "";
|
||||
} else
|
||||
return "" + no;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Dock badge off the {@link Application} to the specified String
|
||||
*
|
||||
* @param app
|
||||
* @param s
|
||||
*/
|
||||
public static void setDockBadge(Application app, String s) {
|
||||
app.setDockIconBadge(s);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Default ImageIcon for the Dock
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ImageIcon getDefaultImage() {
|
||||
ClassLoader loader = ApplePlugin.class.getClassLoader();
|
||||
URL url = loader.getResource("images/Spark-Dock-256-On.png");
|
||||
return new ImageIcon(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bounce the application's dock icon to get the user's attention.
|
||||
*
|
||||
* @param critical Bounce the icon repeatedly if this is true. Bounce it
|
||||
* only for one second (usually just one bounce) if this is false.
|
||||
*
|
||||
* @param critical
|
||||
* Bounce the icon repeatedly if this is true. Bounce it only for
|
||||
* one second (usually just one bounce) if this is false.
|
||||
*/
|
||||
public void bounceDockIcon(boolean critical) {
|
||||
int howMuch = (critical) ?
|
||||
NSApplication.UserAttentionRequestCritical :
|
||||
NSApplication.UserAttentionRequestInformational;
|
||||
|
||||
final int requestID = NSApplication.sharedApplication().requestUserAttention(howMuch);
|
||||
|
||||
// Since NSApplication.requestUserAttention() seems to ignore the
|
||||
// param and always bounces the dock icon continuously no matter
|
||||
// what, make sure it gets cancelled if appropriate.
|
||||
// This is Apple bug #3414391
|
||||
if (!critical) {
|
||||
Thread cancelThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
NSApplication.sharedApplication().cancelUserAttentionRequest(requestID);
|
||||
}
|
||||
});
|
||||
cancelThread.start();
|
||||
|
||||
}
|
||||
|
||||
flash = true;
|
||||
_app.requestUserAttention(critical);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link com.apple.cocoa.application.NSImage} from a string that points to an image in the class
|
||||
*
|
||||
* @param image classpath path of an image
|
||||
* @return an cocoa image object
|
||||
*/
|
||||
public static NSImage getImage(String image) {
|
||||
InputStream in = ApplePlugin.class.getResourceAsStream(image);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buff = new byte[10 * 1024];
|
||||
int len;
|
||||
try {
|
||||
while ((len = in.read(buff)) != -1) {
|
||||
out.write(buff, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Log.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
NSData data = new NSData(out.toByteArray());
|
||||
return new NSImage(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link com.apple.cocoa.application.NSImage} from a string that points to an image in the class
|
||||
*
|
||||
* @param url URL to retrieve image from.
|
||||
* @return an cocoa image object
|
||||
*/
|
||||
public static NSImage getImage(URL url) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = url.openStream();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Log.error(e.getMessage(), e);
|
||||
}
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buff = new byte[10 * 1024];
|
||||
int len;
|
||||
try {
|
||||
if (in != null) {
|
||||
while ((len = in.read(buff)) != -1) {
|
||||
out.write(buff, 0, len);
|
||||
}
|
||||
in.close();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Log.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
NSData data = new NSData(out.toByteArray());
|
||||
return new NSImage(data);
|
||||
}
|
||||
|
||||
public void resetDock() {
|
||||
if (flash) {
|
||||
flash = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static NSImage getImageForMessageCountOn() {
|
||||
int no = SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages();
|
||||
ClassLoader loader = ApplePlugin.class.getClassLoader();
|
||||
if (no > 10) {
|
||||
no = 10;
|
||||
}
|
||||
|
||||
if (no == 0) {
|
||||
URL url = loader.getResource("images/Spark-Dock-256-On.png");
|
||||
return getImage(url);
|
||||
}
|
||||
|
||||
URL url = loader.getResource("images/Spark-Dock-256-" + no + "-On.png");
|
||||
return getImage(url);
|
||||
}
|
||||
|
||||
public static NSImage getImageForMessageCountOff() {
|
||||
int no = SparkManager.getChatManager().getChatContainer().getTotalNumberOfUnreadMessages();
|
||||
ClassLoader loader = ApplePlugin.class.getClassLoader();
|
||||
if (no > 10) {
|
||||
no = 10;
|
||||
}
|
||||
|
||||
if (no == 0) {
|
||||
URL url = loader.getResource("images/Spark-Dock-256-On.png");
|
||||
return getImage(url);
|
||||
}
|
||||
|
||||
URL url = loader.getResource("images/Spark-Dock-256-" + no + "-Off.png");
|
||||
return getImage(url);
|
||||
}
|
||||
|
||||
|
||||
public static NSImage getDefaultImage() {
|
||||
ClassLoader loader = ApplePlugin.class.getClassLoader();
|
||||
URL url = loader.getResource("images/Spark-Dock-256-On.png");
|
||||
return getImage(url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<!-- Define your plugins -->
|
||||
<plugin>
|
||||
<name>Apple Notification Plugin</name>
|
||||
<version>1.0</version>
|
||||
<author>Andrew Wright</author>
|
||||
<name>Mac OSX 10.6 Plugin</name>
|
||||
<version>2.0 - OSX10.6.7</version>
|
||||
<author>Wolf Posdorfer</author>
|
||||
<homePage>http://www.jivesoftware.com</homePage>
|
||||
<email>andrew@jivesoftware.com</email>
|
||||
<description>Gives Spark mac notification capabilities and other enhancements.</description>
|
||||
<email>9posdorf@informatik.uni-hamburg.de</email>
|
||||
<description>Adds MacOSX features to Spark</description>
|
||||
<class>com.jivesoftware.spark.plugin.apple.ApplePlugin</class>
|
||||
<minSparkVersion>2.0.0.1</minSparkVersion>
|
||||
<minSparkVersion>2.6.0</minSparkVersion>
|
||||
</plugin>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user