Compare commits
22 Commits
muwire-0.5
...
muwire-0.5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b412f9fb0c | ||
![]() |
b24d04811d | ||
![]() |
771f645df0 | ||
![]() |
b6483ad0f4 | ||
![]() |
decb72c8ef | ||
![]() |
439b3bf18b | ||
![]() |
06679ffee0 | ||
![]() |
1d5b12e2d7 | ||
![]() |
4e6e1b6f5b | ||
![]() |
f0b5361d7b | ||
![]() |
e0c6bfbf51 | ||
![]() |
2a0ecd8a47 | ||
![]() |
fb1804e849 | ||
![]() |
d4eaa0df8d | ||
![]() |
ffde6ac86f | ||
![]() |
7ad677ead2 | ||
![]() |
ddb0568aab | ||
![]() |
ff50a84a48 | ||
![]() |
770396ba41 | ||
![]() |
b55852e993 | ||
![]() |
a6945275a4 | ||
![]() |
7241809e55 |
@@ -4,7 +4,7 @@ MuWire is an easy to use file-sharing program which offers anonymity using [I2P
|
||||
|
||||
It is inspired by the LimeWire Gnutella client and developped by a former LimeWire developer.
|
||||
|
||||
The current stable release - 0.4.15 is avaiable for download at https://muwire.com. You can find technical documentation in the "doc" folder.
|
||||
The current stable release - 0.5.2 is avaiable for download at https://muwire.com. You can find technical documentation in the "doc" folder.
|
||||
|
||||
### Building
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class Cli {
|
||||
|
||||
Core core
|
||||
try {
|
||||
core = new Core(props, home, "0.5.2")
|
||||
core = new Core(props, home, "0.5.3")
|
||||
} catch (Exception bad) {
|
||||
bad.printStackTrace(System.out)
|
||||
println "Failed to initialize core, exiting"
|
||||
|
@@ -53,7 +53,7 @@ class CliDownloader {
|
||||
|
||||
Core core
|
||||
try {
|
||||
core = new Core(props, home, "0.5.2")
|
||||
core = new Core(props, home, "0.5.3")
|
||||
} catch (Exception bad) {
|
||||
bad.printStackTrace(System.out)
|
||||
println "Failed to initialize core, exiting"
|
||||
|
@@ -375,7 +375,7 @@ public class Core {
|
||||
}
|
||||
}
|
||||
|
||||
Core core = new Core(props, home, "0.5.2")
|
||||
Core core = new Core(props, home, "0.5.3")
|
||||
core.startServices()
|
||||
|
||||
// ... at the end, sleep or execute script
|
||||
|
@@ -95,7 +95,7 @@ class ConnectionAcceptorTest {
|
||||
connectionEstablisher = connectionEstablisherMock.proxyInstance()
|
||||
|
||||
acceptor = new ConnectionAcceptor(eventBus, connectionManager, settings, i2pAcceptor,
|
||||
hostCache, trustService, searchManager, uploadManager, connectionEstablisher)
|
||||
hostCache, trustService, searchManager, uploadManager, null, connectionEstablisher)
|
||||
acceptor.start()
|
||||
Thread.sleep(100)
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
group = com.muwire
|
||||
version = 0.5.2
|
||||
i2pVersion = 0.9.42
|
||||
version = 0.5.3
|
||||
i2pVersion = 0.9.43
|
||||
groovyVersion = 2.4.15
|
||||
slf4jVersion = 1.7.25
|
||||
spockVersion = 1.1-groovy-2.4
|
||||
|
@@ -1,8 +1,8 @@
|
||||
|
||||
application {
|
||||
title = 'MuWire'
|
||||
startupGroups = ['EventList', 'MainFrame']
|
||||
autoShutdown = true
|
||||
startupGroups = ['EventList', 'MainFrame', 'ShutdownWindow']
|
||||
autoShutdown = false
|
||||
}
|
||||
|
||||
mvcGroups {
|
||||
@@ -16,6 +16,11 @@ mvcGroups {
|
||||
view = 'com.muwire.gui.MainFrameView'
|
||||
controller = 'com.muwire.gui.MainFrameController'
|
||||
}
|
||||
'ShutdownWindow' {
|
||||
model = 'com.muwire.gui.ShutdownWindowModel'
|
||||
view = 'com.muwire.gui.ShutdownWindowView'
|
||||
controller = 'com.muwire.gui.ShutdownWindowController'
|
||||
}
|
||||
'SearchTab' {
|
||||
model = 'com.muwire.gui.SearchTabModel'
|
||||
view = 'com.muwire.gui.SearchTabView'
|
||||
@@ -61,4 +66,9 @@ mvcGroups {
|
||||
view = 'com.muwire.gui.BrowseView'
|
||||
controller = 'com.muwire.gui.BrowseController'
|
||||
}
|
||||
'close-warning' {
|
||||
model = 'com.muwire.gui.CloseWarningModel'
|
||||
view = 'com.muwire.gui.CloseWarningView'
|
||||
controller = 'com.muwire.gui.CloseWarningController'
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,39 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import griffon.core.artifact.GriffonController
|
||||
import griffon.core.controller.ControllerAction
|
||||
import griffon.inject.MVCMember
|
||||
import griffon.metadata.ArtifactProviderFor
|
||||
import javax.annotation.Nonnull
|
||||
|
||||
@ArtifactProviderFor(GriffonController)
|
||||
class CloseWarningController {
|
||||
@MVCMember @Nonnull
|
||||
CloseWarningModel model
|
||||
@MVCMember @Nonnull
|
||||
CloseWarningView view
|
||||
|
||||
UISettings settings
|
||||
File home
|
||||
|
||||
|
||||
void mvcGroupInit(Map<String, String> args) {
|
||||
model.closeWarning = settings.closeWarning
|
||||
}
|
||||
|
||||
@ControllerAction
|
||||
void close() {
|
||||
boolean showWarning = !view.checkbox.model.isSelected()
|
||||
model.closeWarning = showWarning
|
||||
settings.closeWarning = showWarning
|
||||
|
||||
File props = new File(home, "gui.properties")
|
||||
props.withOutputStream {
|
||||
settings.write(it)
|
||||
}
|
||||
|
||||
view.dialog.setVisible(false)
|
||||
view.mainFrame.setVisible(false)
|
||||
mvcGroup.destroy()
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import griffon.core.artifact.GriffonController
|
||||
import griffon.core.controller.ControllerAction
|
||||
import griffon.inject.MVCMember
|
||||
import griffon.metadata.ArtifactProviderFor
|
||||
import javax.annotation.Nonnull
|
||||
|
||||
@ArtifactProviderFor(GriffonController)
|
||||
class ShutdownWindowController {
|
||||
}
|
@@ -10,7 +10,9 @@ import com.muwire.gui.UISettings
|
||||
|
||||
import javax.annotation.Nonnull
|
||||
import javax.inject.Inject
|
||||
import javax.swing.ImageIcon
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPopupMenu
|
||||
import javax.swing.JTable
|
||||
import javax.swing.LookAndFeel
|
||||
import javax.swing.UIManager
|
||||
@@ -20,7 +22,11 @@ import static griffon.util.GriffonApplicationUtils.isMacOSX
|
||||
import static groovy.swing.SwingBuilder.lookAndFeel
|
||||
|
||||
import java.awt.Font
|
||||
import java.awt.MenuItem
|
||||
import java.awt.PopupMenu
|
||||
import java.awt.SystemTray
|
||||
import java.awt.Toolkit
|
||||
import java.awt.TrayIcon
|
||||
import java.util.logging.Level
|
||||
import java.util.logging.LogManager
|
||||
|
||||
@@ -43,6 +49,56 @@ class Initialize extends AbstractLifecycleHandler {
|
||||
}
|
||||
}
|
||||
|
||||
System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS");
|
||||
|
||||
if (SystemTray.isSupported() && (SystemVersion.isMac() || SystemVersion.isWindows())) {
|
||||
try {
|
||||
def tray = SystemTray.getSystemTray()
|
||||
def url = Initialize.class.getResource("/MuWire-16x16.png")
|
||||
def image = new ImageIcon(url, "tray icon").getImage()
|
||||
def popupMenu = new PopupMenu()
|
||||
def trayIcon = new TrayIcon(image, "MuWire", popupMenu)
|
||||
|
||||
|
||||
def exit = new MenuItem("Exit")
|
||||
exit.addActionListener({
|
||||
application.getWindowManager().findWindow("main-frame").setVisible(false)
|
||||
application.getWindowManager().findWindow("shutdown-window").setVisible(true)
|
||||
Core core = application.getContext().get("core")
|
||||
if (core != null) {
|
||||
Thread t = new Thread({
|
||||
core.shutdown()
|
||||
application.shutdown()
|
||||
}as Runnable)
|
||||
t.start()
|
||||
} else
|
||||
application.shutdown()
|
||||
tray.remove(trayIcon)
|
||||
})
|
||||
|
||||
def showMW = {e ->
|
||||
def mainFrame = application.getWindowManager().findWindow("main-frame")
|
||||
if (mainFrame != null) {
|
||||
Core core = application.getContext().get("core")
|
||||
if (core != null)
|
||||
mainFrame.setVisible(true)
|
||||
}
|
||||
}
|
||||
|
||||
def show = new MenuItem("Open MuWire")
|
||||
show.addActionListener(showMW)
|
||||
popupMenu.add(show)
|
||||
popupMenu.add(exit)
|
||||
tray.add(trayIcon)
|
||||
|
||||
|
||||
trayIcon.addActionListener(showMW)
|
||||
application.getContext().put("tray-icon", true)
|
||||
} catch (Exception bad) {
|
||||
log.log(Level.WARNING,"couldn't set tray icon",bad)
|
||||
}
|
||||
}
|
||||
|
||||
log.info "Loading home dir"
|
||||
def portableHome = System.getProperty("portable.home")
|
||||
def home = portableHome == null ?
|
||||
|
@@ -20,6 +20,9 @@ class Shutdown extends AbstractLifecycleHandler {
|
||||
void execute() {
|
||||
log.info("shutting down")
|
||||
Core core = application.context.get("core")
|
||||
core.shutdown()
|
||||
if (core != null) {
|
||||
Thread t = new Thread({ core.shutdown() } as Runnable)
|
||||
t.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,15 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import javax.annotation.Nonnull
|
||||
|
||||
import griffon.core.artifact.GriffonController
|
||||
import griffon.core.artifact.GriffonModel
|
||||
import griffon.core.controller.ControllerAction
|
||||
import griffon.inject.MVCMember
|
||||
import griffon.metadata.ArtifactProviderFor
|
||||
import javax.annotation.Nonnull
|
||||
|
||||
@ArtifactProviderFor(GriffonModel)
|
||||
class CloseWarningModel {
|
||||
@griffon.transform.Observable boolean closeWarning
|
||||
}
|
@@ -499,6 +499,8 @@ class MainFrameModel {
|
||||
}
|
||||
|
||||
void onRouterDisconnectedEvent(RouterDisconnectedEvent e) {
|
||||
if (core.getShutdown().get())
|
||||
return
|
||||
runInsideUIAsync {
|
||||
JOptionPane.showMessageDialog(null, "MuWire lost connection to the I2P router and will now exit.",
|
||||
"Connection to I2P router lost", JOptionPane.WARNING_MESSAGE)
|
||||
|
@@ -0,0 +1,9 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import griffon.core.artifact.GriffonModel
|
||||
import griffon.transform.Observable
|
||||
import griffon.metadata.ArtifactProviderFor
|
||||
|
||||
@ArtifactProviderFor(GriffonModel)
|
||||
class ShutdownWindowModel {
|
||||
}
|
58
gui/griffon-app/views/com/muwire/gui/CloseWarningView.groovy
Normal file
58
gui/griffon-app/views/com/muwire/gui/CloseWarningView.groovy
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import griffon.core.artifact.GriffonView
|
||||
import griffon.inject.MVCMember
|
||||
import griffon.metadata.ArtifactProviderFor
|
||||
|
||||
import javax.swing.JDialog
|
||||
import javax.swing.SwingConstants
|
||||
|
||||
import java.awt.GridBagConstraints
|
||||
import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
|
||||
import javax.annotation.Nonnull
|
||||
|
||||
@ArtifactProviderFor(GriffonView)
|
||||
class CloseWarningView {
|
||||
@MVCMember @Nonnull
|
||||
FactoryBuilderSupport builder
|
||||
@MVCMember @Nonnull
|
||||
CloseWarningModel model
|
||||
|
||||
def mainFrame
|
||||
def dialog
|
||||
def panel
|
||||
def checkbox
|
||||
|
||||
void initUI() {
|
||||
mainFrame = application.windowManager.findWindow("main-frame")
|
||||
|
||||
dialog = new JDialog(mainFrame, "MuWire will continue running", true)
|
||||
panel = builder.panel {
|
||||
gridBagLayout()
|
||||
label(text : "MuWire will continue running. You can close it from the system tray", constraints : gbc(gridx: 0, gridy: 0, gridwidth : 2))
|
||||
label(text : "\n", constraints : gbc(gridx : 0, gridy : 1)) // TODO: real padding
|
||||
label(text : "Do not show this warning again", constraints : gbc(gridx: 0, gridy : 2, weightx: 100, anchor : GridBagConstraints.LINE_END))
|
||||
checkbox = checkBox(selected : bind {model.closeWarning}, constraints : gbc(gridx: 1, gridy :2))
|
||||
panel (constraints : gbc(gridx: 0, gridy : 3, gridwidth : 2)) {
|
||||
button(text : "Ok", closeAction)
|
||||
}
|
||||
}
|
||||
dialog.getContentPane().add(panel)
|
||||
dialog.pack()
|
||||
dialog.setResizable(false)
|
||||
dialog.setLocationRelativeTo(mainFrame)
|
||||
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
|
||||
dialog.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosed(WindowEvent e) {
|
||||
mainFrame.setVisible(false)
|
||||
mvcGroup.destroy()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
void mvcGroupInit(Map<String,String> args) {
|
||||
dialog.show()
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import griffon.core.GriffonApplication
|
||||
import griffon.core.artifact.GriffonView
|
||||
import griffon.core.env.Metadata
|
||||
import griffon.inject.MVCMember
|
||||
@@ -11,6 +12,7 @@ import javax.swing.BorderFactory
|
||||
import javax.swing.Box
|
||||
import javax.swing.BoxLayout
|
||||
import javax.swing.JFileChooser
|
||||
import javax.swing.JFrame
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JMenuItem
|
||||
import javax.swing.JPopupMenu
|
||||
@@ -19,6 +21,7 @@ import javax.swing.JTable
|
||||
import javax.swing.JTree
|
||||
import javax.swing.ListSelectionModel
|
||||
import javax.swing.SwingConstants
|
||||
import javax.swing.SwingUtilities
|
||||
import javax.swing.TransferHandler
|
||||
import javax.swing.border.Border
|
||||
import javax.swing.table.DefaultTableCellRenderer
|
||||
@@ -26,6 +29,7 @@ import javax.swing.tree.TreeNode
|
||||
import javax.swing.tree.TreePath
|
||||
|
||||
import com.muwire.core.Constants
|
||||
import com.muwire.core.Core
|
||||
import com.muwire.core.MuWireSettings
|
||||
import com.muwire.core.SharedFile
|
||||
import com.muwire.core.download.Downloader
|
||||
@@ -42,6 +46,8 @@ import java.awt.datatransfer.DataFlavor
|
||||
import java.awt.datatransfer.StringSelection
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import javax.annotation.Nonnull
|
||||
@@ -54,6 +60,7 @@ class MainFrameView {
|
||||
@MVCMember @Nonnull
|
||||
MainFrameModel model
|
||||
|
||||
@Inject @Nonnull GriffonApplication application
|
||||
@Inject Metadata metadata
|
||||
|
||||
def downloadsTable
|
||||
@@ -68,6 +75,7 @@ class MainFrameView {
|
||||
builder.with {
|
||||
application(size : [1024,768], id: 'main-frame',
|
||||
locationRelativeTo : null,
|
||||
defaultCloseOperation : JFrame.DO_NOTHING_ON_CLOSE,
|
||||
title: application.configuration['application.title'] + " " +
|
||||
metadata["application.version"] + " revision " + metadata["build.revision"],
|
||||
iconImage: imageIcon('/MuWire-48x48.png').image,
|
||||
@@ -77,6 +85,9 @@ class MainFrameView {
|
||||
pack : false,
|
||||
visible : bind { model.coreInitialized }) {
|
||||
menuBar {
|
||||
menu (text : "File") {
|
||||
menuItem("Exit", actionPerformed : {closeApplication()})
|
||||
}
|
||||
menu (text : "Options") {
|
||||
menuItem("Configuration", actionPerformed : {mvcGroup.createMVCGroup("Options")})
|
||||
menuItem("Content Control", actionPerformed : {
|
||||
@@ -432,6 +443,22 @@ class MainFrameView {
|
||||
true
|
||||
}
|
||||
})
|
||||
|
||||
mainFrame.addWindowListener(new WindowAdapter(){
|
||||
public void windowClosing(WindowEvent e) {
|
||||
if (application.getContext().get("tray-icon")) {
|
||||
if (settings.closeWarning) {
|
||||
runInsideUIAsync {
|
||||
Map<String, Object> args2 = new HashMap<>()
|
||||
args2.put("settings", settings)
|
||||
args2.put("home", model.core.home)
|
||||
mvcGroup.createMVCGroup("close-warning", "Close Warning", args2)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
closeApplication()
|
||||
}
|
||||
}})
|
||||
|
||||
def downloadsTable = builder.getVariable("downloads-table")
|
||||
def selectionModel = downloadsTable.getSelectionModel()
|
||||
@@ -894,4 +921,18 @@ class MainFrameView {
|
||||
tree.setSelectionPaths(selectedPaths)
|
||||
builder.getVariable("shared-files-table").model.fireTableDataChanged()
|
||||
}
|
||||
|
||||
private void closeApplication() {
|
||||
def mainFrame = builder.getVariable("main-frame")
|
||||
mainFrame.setVisible(false)
|
||||
application.getWindowManager().findWindow("shutdown-window").setVisible(true)
|
||||
Core core = application.getContext().get("core")
|
||||
if (core != null) {
|
||||
Thread t = new Thread({
|
||||
core.shutdown()
|
||||
application.shutdown()
|
||||
}as Runnable)
|
||||
t.start()
|
||||
}
|
||||
}
|
||||
}
|
@@ -188,7 +188,7 @@ class OptionsView {
|
||||
label(text : "Automatically clear cancelled downloads", constraints: gbc(gridx: 0, gridy:0, anchor : GridBagConstraints.LINE_START, weightx: 100))
|
||||
clearCancelledDownloadsCheckbox = checkBox(selected : bind {model.clearCancelledDownloads},
|
||||
constraints : gbc(gridx : 1, gridy:0, anchor : GridBagConstraints.LINE_END))
|
||||
label(text : "Automatically flear finished downloads", constraints: gbc(gridx: 0, gridy:1, anchor : GridBagConstraints.LINE_START, weightx: 100))
|
||||
label(text : "Automatically clear finished downloads", constraints: gbc(gridx: 0, gridy:1, anchor : GridBagConstraints.LINE_START, weightx: 100))
|
||||
clearFinishedDownloadsCheckbox = checkBox(selected : bind {model.clearFinishedDownloads},
|
||||
constraints : gbc(gridx : 1, gridy:1, anchor : GridBagConstraints.LINE_END))
|
||||
label(text : "Smooth download speed over (seconds)", constraints : gbc(gridx: 0, gridy : 2, anchor : GridBagConstraints.LINE_START, weightx: 100))
|
||||
|
@@ -0,0 +1,40 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import griffon.core.GriffonApplication
|
||||
import griffon.core.artifact.GriffonView
|
||||
import griffon.inject.MVCMember
|
||||
import griffon.metadata.ArtifactProviderFor
|
||||
|
||||
import javax.swing.Box
|
||||
import javax.swing.SwingConstants
|
||||
import javax.annotation.Nonnull
|
||||
import javax.inject.Inject
|
||||
|
||||
@ArtifactProviderFor(GriffonView)
|
||||
class ShutdownWindowView {
|
||||
@MVCMember @Nonnull
|
||||
FactoryBuilderSupport builder
|
||||
@MVCMember @Nonnull
|
||||
ShutdownWindowModel model
|
||||
|
||||
void initUI() {
|
||||
builder.with {
|
||||
app = application(size: [320, 80], id: 'shutdown-window',
|
||||
locationRelativeTo : null,
|
||||
title: application.configuration['application.title'],
|
||||
iconImage: imageIcon('/MuWire-48x48.png').image,
|
||||
iconImages: [imageIcon('/MuWire-48x48.png').image,
|
||||
imageIcon('/MuWire-32x32.png').image,
|
||||
imageIcon('/MuWire-16x16.png').image],
|
||||
visible: false ) {
|
||||
panel {
|
||||
vbox {
|
||||
label("MuWire is shutting down, please wait...")
|
||||
Box.createVerticalGlue()
|
||||
progressBar(indeterminate : true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@ class UISettings {
|
||||
boolean clearFinishedDownloads
|
||||
boolean excludeLocalResult
|
||||
boolean showSearchHashes
|
||||
boolean closeWarning
|
||||
|
||||
UISettings(Properties props) {
|
||||
lnf = props.getProperty("lnf", "system")
|
||||
@@ -22,6 +23,7 @@ class UISettings {
|
||||
showSearchHashes = Boolean.parseBoolean(props.getProperty("showSearchHashes","true"))
|
||||
autoFontSize = Boolean.parseBoolean(props.getProperty("autoFontSize","false"))
|
||||
fontSize = Integer.parseInt(props.getProperty("fontSize","12"))
|
||||
closeWarning = Boolean.parseBoolean(props.getProperty("closeWarning","true"))
|
||||
}
|
||||
|
||||
void write(OutputStream out) throws IOException {
|
||||
@@ -34,6 +36,7 @@ class UISettings {
|
||||
props.setProperty("showSearchHashes", String.valueOf(showSearchHashes))
|
||||
props.setProperty("autoFontSize", String.valueOf(autoFontSize))
|
||||
props.setProperty("fontSize", String.valueOf(fontSize))
|
||||
props.setProperty("closeWarning", String.valueOf(closeWarning))
|
||||
if (font != null)
|
||||
props.setProperty("font", font)
|
||||
|
||||
|
Reference in New Issue
Block a user