Compare commits
17 Commits
muwire-0.0
...
muwire-0.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a5d442d320 | ||
![]() |
3f9ee887d6 | ||
![]() |
4a9e6d3b6b | ||
![]() |
80f2cc5f99 | ||
![]() |
12283dba9d | ||
![]() |
5c959bc8b7 | ||
![]() |
f3712fe7af | ||
![]() |
3e49b0ec66 | ||
![]() |
f90beb8e3d | ||
![]() |
fbad7b6c7e | ||
![]() |
ec2d89c18c | ||
![]() |
c27fc0a515 | ||
![]() |
14681c2060 | ||
![]() |
1aeb230ea8 | ||
![]() |
d1dfc73f5a | ||
![]() |
0cebe4119c | ||
![]() |
9f21120ec8 |
@@ -32,7 +32,6 @@ At the moment there are very few nodes on the network, so you will see very few
|
|||||||
|
|
||||||
### Known bugs and limitations
|
### Known bugs and limitations
|
||||||
|
|
||||||
* Sometimes the list of shared files gets lost
|
|
||||||
* Many UI features you would expect are not there yet
|
* Many UI features you would expect are not there yet
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,9 +4,15 @@ import java.util.concurrent.CountDownLatch
|
|||||||
|
|
||||||
import com.muwire.core.Core
|
import com.muwire.core.Core
|
||||||
import com.muwire.core.MuWireSettings
|
import com.muwire.core.MuWireSettings
|
||||||
|
import com.muwire.core.connection.ConnectionAttemptStatus
|
||||||
|
import com.muwire.core.connection.ConnectionEvent
|
||||||
|
import com.muwire.core.connection.DisconnectionEvent
|
||||||
import com.muwire.core.files.AllFilesLoadedEvent
|
import com.muwire.core.files.AllFilesLoadedEvent
|
||||||
import com.muwire.core.files.FileHashedEvent
|
import com.muwire.core.files.FileHashedEvent
|
||||||
|
import com.muwire.core.files.FileLoadedEvent
|
||||||
import com.muwire.core.files.FileSharedEvent
|
import com.muwire.core.files.FileSharedEvent
|
||||||
|
import com.muwire.core.upload.UploadEvent
|
||||||
|
import com.muwire.core.upload.UploadFinishedEvent
|
||||||
|
|
||||||
class Cli {
|
class Cli {
|
||||||
|
|
||||||
@@ -28,28 +34,15 @@ class Cli {
|
|||||||
|
|
||||||
Core core
|
Core core
|
||||||
try {
|
try {
|
||||||
core = new Core(props, home, "0.0.11")
|
core = new Core(props, home, "0.0.13")
|
||||||
} catch (Exception bad) {
|
} catch (Exception bad) {
|
||||||
bad.printStackTrace(System.out)
|
bad.printStackTrace(System.out)
|
||||||
println "Failed to initialize core, exiting"
|
println "Failed to initialize core, exiting"
|
||||||
System.exit(1)
|
System.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
def latch = new CountDownLatch(1)
|
|
||||||
def fileLoader = new Object() {
|
|
||||||
public void onAllFilesLoadedEvent(AllFilesLoadedEvent e) {
|
|
||||||
latch.countDown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
core.eventBus.register(AllFilesLoadedEvent.class, fileLoader)
|
|
||||||
core.startServices()
|
|
||||||
|
|
||||||
println "waiting for files to load"
|
|
||||||
latch.await()
|
|
||||||
|
|
||||||
|
|
||||||
// now we begin
|
|
||||||
println "MuWire is ready"
|
|
||||||
|
|
||||||
def filesList
|
def filesList
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
@@ -62,14 +55,39 @@ class Cli {
|
|||||||
Thread.sleep(1000)
|
Thread.sleep(1000)
|
||||||
println "loading shared files from $filesList"
|
println "loading shared files from $filesList"
|
||||||
|
|
||||||
core.eventBus.register(FileHashedEvent.class, new Object() {
|
// listener for shared files
|
||||||
void onFileHashedEvent(FileHashedEvent e) {
|
def sharedListener = new SharedListener()
|
||||||
if (e.error != null)
|
core.eventBus.register(FileHashedEvent.class, sharedListener)
|
||||||
println "ERROR $e.error"
|
core.eventBus.register(FileLoadedEvent.class, sharedListener)
|
||||||
else
|
|
||||||
println "Shared file : $e.sharedFile.file"
|
// for connections
|
||||||
|
def connectionsListener = new ConnectionListener()
|
||||||
|
core.eventBus.register(ConnectionEvent.class, connectionsListener)
|
||||||
|
core.eventBus.register(DisconnectionEvent.class, connectionsListener)
|
||||||
|
|
||||||
|
// for uploads
|
||||||
|
def uploadsListener = new UploadsListener()
|
||||||
|
core.eventBus.register(UploadEvent.class, uploadsListener)
|
||||||
|
core.eventBus.register(UploadFinishedEvent.class, uploadsListener)
|
||||||
|
|
||||||
|
Timer timer = new Timer("status-printer", true)
|
||||||
|
timer.schedule({
|
||||||
|
println "Connections $connectionsListener.connections Uploads $uploadsListener.uploads Shared $sharedListener.shared"
|
||||||
|
} as TimerTask, 60000, 60000)
|
||||||
|
|
||||||
|
def latch = new CountDownLatch(1)
|
||||||
|
def fileLoader = new Object() {
|
||||||
|
public void onAllFilesLoadedEvent(AllFilesLoadedEvent e) {
|
||||||
|
latch.countDown()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
core.eventBus.register(AllFilesLoadedEvent.class, fileLoader)
|
||||||
|
core.startServices()
|
||||||
|
|
||||||
|
println "waiting for files to load"
|
||||||
|
latch.await()
|
||||||
|
// now we begin
|
||||||
|
println "MuWire is ready"
|
||||||
|
|
||||||
filesList = new File(filesList)
|
filesList = new File(filesList)
|
||||||
filesList.withReader {
|
filesList.withReader {
|
||||||
@@ -83,4 +101,42 @@ class Cli {
|
|||||||
})
|
})
|
||||||
Thread.sleep(Integer.MAX_VALUE)
|
Thread.sleep(Integer.MAX_VALUE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class ConnectionListener {
|
||||||
|
volatile int connections
|
||||||
|
public void onConnectionEvent(ConnectionEvent e) {
|
||||||
|
if (e.status == ConnectionAttemptStatus.SUCCESSFUL)
|
||||||
|
connections++
|
||||||
|
}
|
||||||
|
public void onDisconnectionEvent(DisconnectionEvent e) {
|
||||||
|
connections--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class UploadsListener {
|
||||||
|
volatile int uploads
|
||||||
|
public void onUploadEvent(UploadEvent e) {
|
||||||
|
uploads++
|
||||||
|
println "Starting upload of ${e.uploader.file.getName()} to ${e.uploader.request.downloader.getHumanReadableName()}"
|
||||||
|
}
|
||||||
|
public void onUploadFinishedEvent(UploadFinishedEvent e) {
|
||||||
|
uploads--
|
||||||
|
println "Finished upload of ${e.uploader.file.getName()} to ${e.uploader.request.downloader.getHumanReadableName()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SharedListener {
|
||||||
|
volatile int shared
|
||||||
|
void onFileHashedEvent(FileHashedEvent e) {
|
||||||
|
if (e.error != null)
|
||||||
|
println "ERROR $e.error"
|
||||||
|
else {
|
||||||
|
println "Shared file : $e.sharedFile.file"
|
||||||
|
shared++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void onFileLoadedEvent(FileLoadedEvent e) {
|
||||||
|
shared++
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -248,7 +248,7 @@ public class Core {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Core core = new Core(props, home, "0.0.11")
|
Core core = new Core(props, home, "0.0.13")
|
||||||
core.startServices()
|
core.startServices()
|
||||||
|
|
||||||
// ... at the end, sleep or execute script
|
// ... at the end, sleep or execute script
|
||||||
|
@@ -3,6 +3,7 @@ package com.muwire.core
|
|||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
import java.util.logging.Level
|
||||||
|
|
||||||
import com.muwire.core.files.FileSharedEvent
|
import com.muwire.core.files.FileSharedEvent
|
||||||
|
|
||||||
@@ -23,14 +24,18 @@ class EventBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void publishInternal(Event e) {
|
private void publishInternal(Event e) {
|
||||||
log.fine "publishing event $e of type ${e.getClass().getSimpleName()}"
|
log.fine "publishing event $e of type ${e.getClass().getSimpleName()} event $e"
|
||||||
def currentHandlers
|
def currentHandlers
|
||||||
final def clazz = e.getClass()
|
final def clazz = e.getClass()
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
currentHandlers = handlers.getOrDefault(clazz, [])
|
currentHandlers = handlers.getOrDefault(clazz, [])
|
||||||
}
|
}
|
||||||
currentHandlers.each {
|
currentHandlers.each {
|
||||||
it."on${clazz.getSimpleName()}"(e)
|
try {
|
||||||
|
it."on${clazz.getSimpleName()}"(e)
|
||||||
|
} catch (Exception bad) {
|
||||||
|
log.log(Level.SEVERE, "exception dispatching event",bad)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -127,6 +127,8 @@ abstract class Connection implements Closeable {
|
|||||||
query.uuid = e.searchEvent.getUuid()
|
query.uuid = e.searchEvent.getUuid()
|
||||||
query.firstHop = e.firstHop
|
query.firstHop = e.firstHop
|
||||||
query.keywords = e.searchEvent.getSearchTerms()
|
query.keywords = e.searchEvent.getSearchTerms()
|
||||||
|
if (e.searchEvent.searchHash != null)
|
||||||
|
query.infohash = Base64.encode(e.searchEvent.searchHash)
|
||||||
query.replyTo = e.replyTo.toBase64()
|
query.replyTo = e.replyTo.toBase64()
|
||||||
if (e.originator != null)
|
if (e.originator != null)
|
||||||
query.originator = e.originator.toBase64()
|
query.originator = e.originator.toBase64()
|
||||||
@@ -155,8 +157,11 @@ abstract class Connection implements Closeable {
|
|||||||
|
|
||||||
protected void handleSearch(def search) {
|
protected void handleSearch(def search) {
|
||||||
UUID uuid = UUID.fromString(search.uuid)
|
UUID uuid = UUID.fromString(search.uuid)
|
||||||
if (search.infohash != null)
|
byte [] infohash = null
|
||||||
|
if (search.infohash != null) {
|
||||||
search.keywords = null
|
search.keywords = null
|
||||||
|
infohash = Base64.decode(search.infohash)
|
||||||
|
}
|
||||||
|
|
||||||
Destination replyTo = new Destination(search.replyTo)
|
Destination replyTo = new Destination(search.replyTo)
|
||||||
TrustLevel trustLevel = trustService.getLevel(replyTo)
|
TrustLevel trustLevel = trustService.getLevel(replyTo)
|
||||||
@@ -180,7 +185,7 @@ abstract class Connection implements Closeable {
|
|||||||
|
|
||||||
|
|
||||||
SearchEvent searchEvent = new SearchEvent(searchTerms : search.keywords,
|
SearchEvent searchEvent = new SearchEvent(searchTerms : search.keywords,
|
||||||
searchHash : search.infohash,
|
searchHash : infohash,
|
||||||
uuid : uuid)
|
uuid : uuid)
|
||||||
QueryEvent event = new QueryEvent ( searchEvent : searchEvent,
|
QueryEvent event = new QueryEvent ( searchEvent : searchEvent,
|
||||||
replyTo : replyTo,
|
replyTo : replyTo,
|
||||||
|
@@ -13,4 +13,8 @@ class QueryEvent extends Event {
|
|||||||
Persona originator
|
Persona originator
|
||||||
Destination receivedOn
|
Destination receivedOn
|
||||||
|
|
||||||
|
String toString() {
|
||||||
|
"searchEvent: $searchEvent firstHop:$firstHop, replyTo:${replyTo.toBase32()}" +
|
||||||
|
"originator: ${originator.getHumanReadableName()} receivedOn: ${receivedOn.toBase32()}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,18 @@
|
|||||||
package com.muwire.core.search
|
package com.muwire.core.search
|
||||||
|
|
||||||
import com.muwire.core.Event
|
import com.muwire.core.Event
|
||||||
|
import com.muwire.core.InfoHash
|
||||||
|
|
||||||
class SearchEvent extends Event {
|
class SearchEvent extends Event {
|
||||||
|
|
||||||
List<String> searchTerms
|
List<String> searchTerms
|
||||||
byte [] searchHash
|
byte [] searchHash
|
||||||
UUID uuid
|
UUID uuid
|
||||||
|
|
||||||
|
String toString() {
|
||||||
|
def infoHash = null
|
||||||
|
if (searchHash != null)
|
||||||
|
infoHash = new InfoHash(searchHash)
|
||||||
|
"searchTerms: $searchTerms searchHash:$infoHash, uuid:$uuid"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
package com.muwire.core.update
|
package com.muwire.core.update
|
||||||
|
|
||||||
import com.muwire.core.Event
|
import com.muwire.core.Event
|
||||||
|
import com.muwire.core.InfoHash
|
||||||
|
|
||||||
class UpdateAvailableEvent extends Event {
|
class UpdateAvailableEvent extends Event {
|
||||||
String version
|
String version
|
||||||
String signer
|
String signer
|
||||||
|
String infoHash
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,7 @@ class UpdateClient {
|
|||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
session.addMuxedSessionListener(new Listener(), I2PSession.PROTO_DATAGRAM, 2)
|
session.addMuxedSessionListener(new Listener(), I2PSession.PROTO_DATAGRAM, 2)
|
||||||
timer.schedule({checkUpdate()} as TimerTask, 30000, 60 * 60 * 1000)
|
timer.schedule({checkUpdate()} as TimerTask, 60000, 60 * 60 * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
@@ -107,7 +107,7 @@ class UpdateClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.info("new version $payload.version available, publishing event")
|
log.info("new version $payload.version available, publishing event")
|
||||||
eventBus.publish(new UpdateAvailableEvent(version : payload.version, signer : payload.signer))
|
eventBus.publish(new UpdateAvailableEvent(version : payload.version, signer : payload.signer, infoHash : payload.infoHash))
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.log(Level.WARNING,"Invalid datagram",e)
|
log.log(Level.WARNING,"Invalid datagram",e)
|
||||||
|
@@ -77,13 +77,15 @@ public class InfoHash {
|
|||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String rv = "InfoHash[root:"+Base32.encode(root) + " hashList:";
|
String rv = "InfoHash[root:"+Base32.encode(root) + " hashList:";
|
||||||
List<String> b32HashList = new ArrayList<>(hashList.length / SIZE);
|
List<String> b64HashList = new ArrayList<>();
|
||||||
byte [] tmp = new byte[SIZE];
|
if (hashList != null) {
|
||||||
for (int i = 0; i < hashList.length / SIZE; i++) {
|
byte [] tmp = new byte[SIZE];
|
||||||
System.arraycopy(hashList, SIZE * i, tmp, 0, SIZE);
|
for (int i = 0; i < hashList.length / SIZE; i++) {
|
||||||
b32HashList.add(Base32.encode(tmp));
|
System.arraycopy(hashList, SIZE * i, tmp, 0, SIZE);
|
||||||
|
b64HashList.add(Base32.encode(tmp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rv += b32HashList.toString();
|
rv += b64HashList.toString();
|
||||||
rv += "]";
|
rv += "]";
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
group = com.muwire
|
group = com.muwire
|
||||||
version = 0.0.11
|
version = 0.0.13
|
||||||
groovyVersion = 2.4.15
|
groovyVersion = 2.4.15
|
||||||
slf4jVersion = 1.7.25
|
slf4jVersion = 1.7.25
|
||||||
spockVersion = 1.1-groovy-2.4
|
spockVersion = 1.1-groovy-2.4
|
||||||
|
@@ -7,6 +7,8 @@ import griffon.core.mvc.MVCGroup
|
|||||||
import griffon.core.mvc.MVCGroupConfiguration
|
import griffon.core.mvc.MVCGroupConfiguration
|
||||||
import griffon.inject.MVCMember
|
import griffon.inject.MVCMember
|
||||||
import griffon.metadata.ArtifactProviderFor
|
import griffon.metadata.ArtifactProviderFor
|
||||||
|
import net.i2p.data.Base64
|
||||||
|
|
||||||
import javax.annotation.Nonnull
|
import javax.annotation.Nonnull
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -42,15 +44,36 @@ class MainFrameController {
|
|||||||
params["uuid"] = uuid.toString()
|
params["uuid"] = uuid.toString()
|
||||||
def group = mvcGroup.createMVCGroup("SearchTab", uuid.toString(), params)
|
def group = mvcGroup.createMVCGroup("SearchTab", uuid.toString(), params)
|
||||||
model.results[uuid.toString()] = group
|
model.results[uuid.toString()] = group
|
||||||
|
|
||||||
// this can be improved a lot
|
def searchEvent
|
||||||
def terms = search.toLowerCase().trim().split(Constants.SPLIT_PATTERN)
|
if (model.hashSearch) {
|
||||||
def searchEvent = new SearchEvent(searchTerms : terms, uuid : uuid)
|
searchEvent = new SearchEvent(searchHash : Base64.decode(search), uuid : uuid)
|
||||||
|
} else {
|
||||||
|
// this can be improved a lot
|
||||||
|
def terms = search.toLowerCase().trim().split(Constants.SPLIT_PATTERN)
|
||||||
|
searchEvent = new SearchEvent(searchTerms : terms, uuid : uuid)
|
||||||
|
}
|
||||||
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : true,
|
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : true,
|
||||||
replyTo: core.me.destination, receivedOn: core.me.destination,
|
replyTo: core.me.destination, receivedOn: core.me.destination,
|
||||||
originator : core.me))
|
originator : core.me))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void search(String infoHash, String tabTitle) {
|
||||||
|
def cardsPanel = builder.getVariable("cards-panel")
|
||||||
|
cardsPanel.getLayout().show(cardsPanel, "search window")
|
||||||
|
def uuid = UUID.randomUUID()
|
||||||
|
Map<String, Object> params = new HashMap<>()
|
||||||
|
params["search-terms"] = tabTitle
|
||||||
|
params["uuid"] = uuid.toString()
|
||||||
|
def group = mvcGroup.createMVCGroup("SearchTab", uuid.toString(), params)
|
||||||
|
model.results[uuid.toString()] = group
|
||||||
|
|
||||||
|
def searchEvent = new SearchEvent(searchHash : Base64.decode(infoHash), uuid:uuid)
|
||||||
|
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : true,
|
||||||
|
replyTo: core.me.destination, receivedOn: core.me.destination,
|
||||||
|
originator : core.me))
|
||||||
|
}
|
||||||
|
|
||||||
private def selectedResult() {
|
private def selectedResult() {
|
||||||
def selected = builder.getVariable("result-tabs").getSelectedComponent()
|
def selected = builder.getVariable("result-tabs").getSelectedComponent()
|
||||||
def group = selected.getClientProperty("mvc-group")
|
def group = selected.getClientProperty("mvc-group")
|
||||||
@@ -137,6 +160,16 @@ class MainFrameController {
|
|||||||
markTrust("trusted-table", TrustLevel.NEUTRAL, model.trusted)
|
markTrust("trusted-table", TrustLevel.NEUTRAL, model.trusted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ControllerAction
|
||||||
|
void keywordSearch() {
|
||||||
|
model.hashSearch = false
|
||||||
|
}
|
||||||
|
|
||||||
|
@ControllerAction
|
||||||
|
void hashSearch() {
|
||||||
|
model.hashSearch = true
|
||||||
|
}
|
||||||
|
|
||||||
void mvcGroupInit(Map<String, String> args) {
|
void mvcGroupInit(Map<String, String> args) {
|
||||||
application.addPropertyChangeListener("core", {e->
|
application.addPropertyChangeListener("core", {e->
|
||||||
core = e.getNewValue()
|
core = e.getNewValue()
|
||||||
|
@@ -29,6 +29,7 @@ import com.muwire.core.upload.UploadFinishedEvent
|
|||||||
|
|
||||||
import griffon.core.GriffonApplication
|
import griffon.core.GriffonApplication
|
||||||
import griffon.core.artifact.GriffonModel
|
import griffon.core.artifact.GriffonModel
|
||||||
|
import griffon.core.env.Metadata
|
||||||
import griffon.core.mvc.MVCGroup
|
import griffon.core.mvc.MVCGroup
|
||||||
import griffon.inject.MVCMember
|
import griffon.inject.MVCMember
|
||||||
import griffon.transform.FXObservable
|
import griffon.transform.FXObservable
|
||||||
@@ -38,8 +39,11 @@ import griffon.metadata.ArtifactProviderFor
|
|||||||
|
|
||||||
@ArtifactProviderFor(GriffonModel)
|
@ArtifactProviderFor(GriffonModel)
|
||||||
class MainFrameModel {
|
class MainFrameModel {
|
||||||
|
@Inject Metadata metadata
|
||||||
@MVCMember @Nonnull
|
@MVCMember @Nonnull
|
||||||
FactoryBuilderSupport builder
|
FactoryBuilderSupport builder
|
||||||
|
@MVCMember @Nonnull
|
||||||
|
MainFrameController controller
|
||||||
@Inject @Nonnull GriffonApplication application
|
@Inject @Nonnull GriffonApplication application
|
||||||
@Observable boolean coreInitialized = false
|
@Observable boolean coreInitialized = false
|
||||||
|
|
||||||
@@ -52,6 +56,8 @@ class MainFrameModel {
|
|||||||
def trusted = []
|
def trusted = []
|
||||||
def distrusted = []
|
def distrusted = []
|
||||||
|
|
||||||
|
boolean hashSearch
|
||||||
|
|
||||||
@Observable int connections
|
@Observable int connections
|
||||||
@Observable String me
|
@Observable String me
|
||||||
@Observable boolean searchButtonsEnabled
|
@Observable boolean searchButtonsEnabled
|
||||||
@@ -260,7 +266,13 @@ class MainFrameModel {
|
|||||||
|
|
||||||
void onUpdateAvailableEvent(UpdateAvailableEvent e) {
|
void onUpdateAvailableEvent(UpdateAvailableEvent e) {
|
||||||
runInsideUIAsync {
|
runInsideUIAsync {
|
||||||
JOptionPane.showMessageDialog(null, "A new version of MuWire is available from $e.signer. Please update to $e.version")
|
|
||||||
|
int option = JOptionPane.showConfirmDialog(null,
|
||||||
|
"MuWire $e.version is available from $e.signer. You have "+ metadata["application.version"]+" Update?",
|
||||||
|
"New MuWire version availble", JOptionPane.OK_CANCEL_OPTION)
|
||||||
|
if (option == JOptionPane.CANCEL_OPTION)
|
||||||
|
return
|
||||||
|
controller.search(e.infoHash,"MuWire update")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,6 +76,12 @@ class MainFrameView {
|
|||||||
|
|
||||||
}
|
}
|
||||||
panel( constraints: BorderLayout.EAST) {
|
panel( constraints: BorderLayout.EAST) {
|
||||||
|
panel {
|
||||||
|
buttonGroup(id : "searchButtonGroup")
|
||||||
|
radioButton(text : "Keywords", selected : true, buttonGroup : searchButtonGroup, keywordSearchAction)
|
||||||
|
radioButton(text : "Hash", selected : false, buttonGroup : searchButtonGroup, hashSearchAction)
|
||||||
|
|
||||||
|
}
|
||||||
button(text: "Search", searchAction)
|
button(text: "Search", searchAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user