Compare commits

...

21 Commits

Author SHA1 Message Date
Zlatin Balevsky
f72cf91462 wait for files to be loaded before sharing watched directories 2019-06-25 22:24:32 +01:00
Zlatin Balevsky
a655c4ef50 add toString 2019-06-25 22:24:15 +01:00
Zlatin Balevsky
5d46e9b796 switch 4_ to INFO 2019-06-25 21:50:15 +01:00
Zlatin Balevsky
642e6e67b3 wait for all files loaded before watching dirs 2019-06-25 21:43:07 +01:00
Zlatin Balevsky
2b6b86f903 show how many pieces the remote side already has 2019-06-25 17:44:05 +01:00
Zlatin Balevsky
f2706a4426 clarify upload column 2019-06-25 17:24:42 +01:00
Zlatin Balevsky
1af75413aa update for brackets 2019-06-25 16:27:02 +01:00
Zlatin Balevsky
adc4077b1a filter asterix 2019-06-25 15:54:30 +01:00
Zlatin Balevsky
01f4e2453b limit search length to 128 characters 2019-06-25 15:53:53 +01:00
Zlatin Balevsky
61267374dd move button around 2019-06-25 08:10:20 +01:00
Zlatin Balevsky
970f814685 make mesh expiration configurable 2019-06-25 08:04:57 +01:00
Zlatin Balevsky
4fd9fc1991 add option to change download location 2019-06-25 07:59:30 +01:00
Zlatin Balevsky
26207ffd1b add constructor 2019-06-25 07:53:24 +01:00
Zlatin Balevsky
2614cfbe5f make host clear interval configurable 2019-06-25 07:41:20 +01:00
Zlatin Balevsky
f11d461ec0 make download sequential ratio a property 2019-06-25 07:34:26 +01:00
Zlatin Balevsky
b2eb2d2755 show hidden files in file choosers 2019-06-24 23:09:20 +01:00
Zlatin Balevsky
ea46a54f19 enable AA by default 2019-06-24 22:55:26 +01:00
Zlatin Balevsky
627add45ad remove griffon icons 2019-06-24 22:51:43 +01:00
Zlatin Balevsky
d364855459 logo 2019-06-24 22:13:03 +01:00
Zlatin Balevsky
14ee35e77a Release 0.3.9 2019-06-24 18:39:59 +01:00
Zlatin Balevsky
8773eb4ee0 fix piece size calculation 2019-06-24 18:29:00 +01:00
41 changed files with 126 additions and 44 deletions

View File

@@ -35,7 +35,7 @@ class Cli {
Core core Core core
try { try {
core = new Core(props, home, "0.3.8") core = new Core(props, home, "0.3.9")
} 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"

View File

@@ -53,7 +53,7 @@ class CliDownloader {
Core core Core core
try { try {
core = new Core(props, home, "0.3.8") core = new Core(props, home, "0.3.9")
} 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"

View File

@@ -9,7 +9,5 @@ class Constants {
public static final int MAX_HEADER_SIZE = 0x1 << 14 public static final int MAX_HEADER_SIZE = 0x1 << 14
public static final int MAX_HEADERS = 16 public static final int MAX_HEADERS = 16
public static final float DOWNLOAD_SEQUENTIAL_RATIO = 0.8f public static final String SPLIT_PATTERN = "[\\*\\+\\-,\\.:;\\(\\)=_/\\\\\\!\\\"\\\'\\\$%\\|\\[\\]\\{\\}]"
public static final String SPLIT_PATTERN = "[\\+\\-,\\.:;\\(\\)=_/\\\\\\!\\\"\\\'\\\$%\\|]"
} }

View File

@@ -27,6 +27,7 @@ import com.muwire.core.files.FileSharedEvent
import com.muwire.core.files.FileUnsharedEvent import com.muwire.core.files.FileUnsharedEvent
import com.muwire.core.files.HasherService import com.muwire.core.files.HasherService
import com.muwire.core.files.PersisterService import com.muwire.core.files.PersisterService
import com.muwire.core.files.AllFilesLoadedEvent
import com.muwire.core.files.DirectoryWatcher import com.muwire.core.files.DirectoryWatcher
import com.muwire.core.hostcache.CacheClient import com.muwire.core.hostcache.CacheClient
import com.muwire.core.hostcache.HostCache import com.muwire.core.hostcache.HostCache
@@ -173,7 +174,7 @@ public class Core {
eventBus.register(SearchEvent.class, fileManager) eventBus.register(SearchEvent.class, fileManager)
log.info("initializing mesh manager") log.info("initializing mesh manager")
MeshManager meshManager = new MeshManager(fileManager, home) MeshManager meshManager = new MeshManager(fileManager, home, props)
eventBus.register(SourceDiscoveredEvent.class, meshManager) eventBus.register(SourceDiscoveredEvent.class, meshManager)
log.info "initializing persistence service" log.info "initializing persistence service"
@@ -236,6 +237,7 @@ public class Core {
log.info("initializing directory watcher") log.info("initializing directory watcher")
directoryWatcher = new DirectoryWatcher(eventBus, fileManager) directoryWatcher = new DirectoryWatcher(eventBus, fileManager)
eventBus.register(FileSharedEvent.class, directoryWatcher) eventBus.register(FileSharedEvent.class, directoryWatcher)
eventBus.register(AllFilesLoadedEvent.class, directoryWatcher)
log.info("initializing hasher service") log.info("initializing hasher service")
hasherService = new HasherService(new FileHasher(), eventBus, fileManager) hasherService = new HasherService(new FileHasher(), eventBus, fileManager)
@@ -244,7 +246,6 @@ public class Core {
public void startServices() { public void startServices() {
hasherService.start() hasherService.start()
directoryWatcher.start()
trustService.start() trustService.start()
trustService.waitForLoad() trustService.waitForLoad()
hostCache.start() hostCache.start()
@@ -297,7 +298,7 @@ public class Core {
} }
} }
Core core = new Core(props, home, "0.3.8") Core core = new Core(props, home, "0.3.9")
core.startServices() core.startServices()
// ... at the end, sleep or execute script // ... at the end, sleep or execute script

View File

@@ -18,6 +18,9 @@ class MuWireSettings {
CrawlerResponse crawlerResponse CrawlerResponse crawlerResponse
boolean shareDownloadedFiles boolean shareDownloadedFiles
Set<String> watchedDirectories Set<String> watchedDirectories
float downloadSequentialRatio
int hostClearInterval
int meshExpiration
MuWireSettings() { MuWireSettings() {
this(new Properties()) this(new Properties())
@@ -33,6 +36,9 @@ class MuWireSettings {
downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","1")) downloadRetryInterval = Integer.parseInt(props.getProperty("downloadRetryInterval","1"))
updateCheckInterval = Integer.parseInt(props.getProperty("updateCheckInterval","24")) updateCheckInterval = Integer.parseInt(props.getProperty("updateCheckInterval","24"))
shareDownloadedFiles = Boolean.parseBoolean(props.getProperty("shareDownloadedFiles","true")) shareDownloadedFiles = Boolean.parseBoolean(props.getProperty("shareDownloadedFiles","true"))
downloadSequentialRatio = Float.valueOf(props.getProperty("downloadSequentialRatio","0.8"))
hostClearInterval = Integer.valueOf(props.getProperty("hostClearInterval","60"))
meshExpiration = Integer.valueOf(props.getProperty("meshExpiration","60"))
watchedDirectories = new HashSet<>() watchedDirectories = new HashSet<>()
if (props.containsKey("watchedDirectories")) { if (props.containsKey("watchedDirectories")) {
@@ -52,6 +58,9 @@ class MuWireSettings {
props.setProperty("downloadRetryInterval", String.valueOf(downloadRetryInterval)) props.setProperty("downloadRetryInterval", String.valueOf(downloadRetryInterval))
props.setProperty("updateCheckInterval", String.valueOf(updateCheckInterval)) props.setProperty("updateCheckInterval", String.valueOf(updateCheckInterval))
props.setProperty("shareDownloadedFiles", String.valueOf(shareDownloadedFiles)) props.setProperty("shareDownloadedFiles", String.valueOf(shareDownloadedFiles))
props.setProperty("downloadSequentialRatio", String.valueOf(downloadSequentialRatio))
props.setProperty("hostClearInterval", String.valueOf(hostClearInterval))
props.setProperty("meshExpiration", String.valueOf(meshExpiration))
if (!watchedDirectories.isEmpty()) { if (!watchedDirectories.isEmpty()) {
String encoded = watchedDirectories.stream(). String encoded = watchedDirectories.stream().

View File

@@ -47,7 +47,7 @@ class DirectoryWatcher {
publisherThread.setDaemon(true) publisherThread.setDaemon(true)
} }
void start() { void onAllFilesLoadedEvent(AllFilesLoadedEvent e) {
watchService = FileSystems.getDefault().newWatchService() watchService = FileSystems.getDefault().newWatchService()
watcherThread.start() watcherThread.start()
publisherThread.start() publisherThread.start()
@@ -55,9 +55,9 @@ class DirectoryWatcher {
void stop() { void stop() {
shutdown = true shutdown = true
watcherThread.interrupt() watcherThread?.interrupt()
publisherThread.interrupt() publisherThread?.interrupt()
watchService.close() watchService?.close()
} }
void onFileSharedEvent(FileSharedEvent e) { void onFileSharedEvent(FileSharedEvent e) {

View File

@@ -7,4 +7,10 @@ class FileHashedEvent extends Event {
SharedFile sharedFile SharedFile sharedFile
String error String error
@Override
public String toString() {
super.toString() + " sharedFile " + sharedFile?.file.getAbsolutePath() + " error: $error"
}
} }

View File

@@ -5,4 +5,9 @@ import com.muwire.core.Event
class FileSharedEvent extends Event { class FileSharedEvent extends Event {
File file File file
@Override
public String toString() {
return super.toString() + " file: "+file.getAbsolutePath()
}
} }

View File

@@ -5,14 +5,15 @@ import net.i2p.data.Destination
class Host { class Host {
private static final int MAX_FAILURES = 3 private static final int MAX_FAILURES = 3
private static final int CLEAR_INTERVAL = 60 * 60 * 1000
final Destination destination final Destination destination
private final int clearInterval
int failures,successes int failures,successes
long lastAttempt long lastAttempt
public Host(Destination destination) { public Host(Destination destination, int clearInterval) {
this.destination = destination this.destination = destination
this.clearInterval = clearInterval
} }
synchronized void onConnect() { synchronized void onConnect() {
@@ -40,6 +41,6 @@ class Host {
} }
synchronized void canTryAgain() { synchronized void canTryAgain() {
System.currentTimeMillis() - lastAttempt > CLEAR_INTERVAL System.currentTimeMillis() - lastAttempt > (clearInterval * 60 * 1000)
} }
} }

View File

@@ -52,7 +52,7 @@ class HostCache extends Service {
hosts.get(e.destination).clearFailures() hosts.get(e.destination).clearFailures()
return return
} }
Host host = new Host(e.destination) Host host = new Host(e.destination, settings.hostClearInterval)
if (allowHost(host)) { if (allowHost(host)) {
hosts.put(e.destination, host) hosts.put(e.destination, host)
} }
@@ -64,7 +64,7 @@ class HostCache extends Service {
Destination dest = e.endpoint.destination Destination dest = e.endpoint.destination
Host host = hosts.get(dest) Host host = hosts.get(dest)
if (host == null) { if (host == null) {
host = new Host(dest) host = new Host(dest, settings.hostClearInterval)
hosts.put(dest, host) hosts.put(dest, host)
} }
@@ -106,7 +106,7 @@ class HostCache extends Service {
storage.eachLine { storage.eachLine {
def entry = slurper.parseText(it) def entry = slurper.parseText(it)
Destination dest = new Destination(entry.destination) Destination dest = new Destination(entry.destination)
Host host = new Host(dest) Host host = new Host(dest, settings.hostClearInterval)
host.failures = Integer.valueOf(String.valueOf(entry.failures)) host.failures = Integer.valueOf(String.valueOf(entry.failures))
host.successes = Integer.valueOf(String.valueOf(entry.successes)) host.successes = Integer.valueOf(String.valueOf(entry.successes))
if (entry.lastAttempt != null) if (entry.lastAttempt != null)

View File

@@ -4,6 +4,7 @@ import java.util.stream.Collectors
import com.muwire.core.Constants import com.muwire.core.Constants
import com.muwire.core.InfoHash import com.muwire.core.InfoHash
import com.muwire.core.MuWireSettings
import com.muwire.core.Persona import com.muwire.core.Persona
import com.muwire.core.download.Pieces import com.muwire.core.download.Pieces
import com.muwire.core.download.SourceDiscoveredEvent import com.muwire.core.download.SourceDiscoveredEvent
@@ -16,15 +17,15 @@ import net.i2p.data.Base64
class MeshManager { class MeshManager {
private static final int EXPIRATION = 60 * 60 * 1000
private final Map<InfoHash, Mesh> meshes = Collections.synchronizedMap(new HashMap<>()) private final Map<InfoHash, Mesh> meshes = Collections.synchronizedMap(new HashMap<>())
private final FileManager fileManager private final FileManager fileManager
private final File home private final File home
private final MuWireSettings settings
MeshManager(FileManager fileManager, File home) { MeshManager(FileManager fileManager, File home, MuWireSettings settings) {
this.fileManager = fileManager this.fileManager = fileManager
this.home = home this.home = home
this.settings = settings
load() load()
} }
@@ -36,7 +37,7 @@ class MeshManager {
synchronized(meshes) { synchronized(meshes) {
if (meshes.containsKey(infoHash)) if (meshes.containsKey(infoHash))
return meshes.get(infoHash) return meshes.get(infoHash)
Pieces pieces = new Pieces(nPieces, Constants.DOWNLOAD_SEQUENTIAL_RATIO) Pieces pieces = new Pieces(nPieces, settings.downloadSequentialRatio)
if (fileManager.rootToFiles.containsKey(infoHash)) { if (fileManager.rootToFiles.containsKey(infoHash)) {
for (int i = 0; i < nPieces; i++) for (int i = 0; i < nPieces; i++)
pieces.markDownloaded(i) pieces.markDownloaded(i)
@@ -80,10 +81,10 @@ class MeshManager {
JsonSlurper slurper = new JsonSlurper() JsonSlurper slurper = new JsonSlurper()
meshFile.eachLine { meshFile.eachLine {
def json = slurper.parseText(it) def json = slurper.parseText(it)
if (now - json.timestamp > EXPIRATION) if (now - json.timestamp > settings.meshExpiration * 60 * 1000)
return return
InfoHash infoHash = new InfoHash(Base64.decode(json.infoHash)) InfoHash infoHash = new InfoHash(Base64.decode(json.infoHash))
Pieces pieces = new Pieces(json.nPieces, Constants.DOWNLOAD_SEQUENTIAL_RATIO) Pieces pieces = new Pieces(json.nPieces, settings.downloadSequentialRatio)
Mesh mesh = new Mesh(infoHash, pieces) Mesh mesh = new Mesh(infoHash, pieces)
json.sources.each { source -> json.sources.each { source ->

View File

@@ -2,5 +2,5 @@ package com.muwire.core.upload
class ContentRequest extends Request { class ContentRequest extends Request {
Range range Range range
boolean have int have
} }

View File

@@ -105,4 +105,14 @@ class ContentUploader extends Uploader {
request.downloader.getHumanReadableName() request.downloader.getHumanReadableName()
} }
@Override
public int getDonePieces() {
return request.have;
}
@Override
public int getTotalPieces() {
return mesh.pieces.nPieces;
}
} }

View File

@@ -50,6 +50,16 @@ class HashListUploader extends Uploader {
public String getDownloader() { public String getDownloader() {
request.downloader.getHumanReadableName() request.downloader.getHumanReadableName()
} }
@Override
public int getDonePieces() {
return 0;
}
@Override
public int getTotalPieces() {
return 1;
}
} }

View File

@@ -50,10 +50,10 @@ class Request {
downloader = new Persona(new ByteArrayInputStream(decoded)) downloader = new Persona(new ByteArrayInputStream(decoded))
} }
boolean have = false int have = 0
if (headers.containsKey("X-Have")) { if (headers.containsKey("X-Have")) {
def encoded = headers["X-Have"].trim() def encoded = headers["X-Have"].trim()
have = DataUtil.decodeXHave(encoded).size() > 0 have = DataUtil.decodeXHave(encoded).size()
} }
new ContentRequest( infoHash : infoHash, range : new Range(start, end), new ContentRequest( infoHash : infoHash, range : new Range(start, end),
headers : headers, downloader : downloader, have : have) headers : headers, downloader : downloader, have : have)

View File

@@ -80,7 +80,7 @@ public class UploadManager {
return return
} }
if (request.have) if (request.have > 0)
eventBus.publish(new SourceDiscoveredEvent(infoHash : request.infoHash, source : request.downloader)) eventBus.publish(new SourceDiscoveredEvent(infoHash : request.infoHash, source : request.downloader))
Mesh mesh Mesh mesh
@@ -205,7 +205,7 @@ public class UploadManager {
return return
} }
if (request.have) if (request.have > 0)
eventBus.publish(new SourceDiscoveredEvent(infoHash : request.infoHash, source : request.downloader)) eventBus.publish(new SourceDiscoveredEvent(infoHash : request.infoHash, source : request.downloader))
Mesh mesh Mesh mesh

View File

@@ -32,4 +32,8 @@ abstract class Uploader {
abstract int getProgress(); abstract int getProgress();
abstract String getDownloader(); abstract String getDownloader();
abstract int getDonePieces();
abstract int getTotalPieces()
} }

View File

@@ -30,7 +30,7 @@ public class SharedFile {
long length = file.length(); long length = file.length();
int rawPieceSize = 0x1 << pieceSize; int rawPieceSize = 0x1 << pieceSize;
int rv = (int) (length / rawPieceSize); int rv = (int) (length / rawPieceSize);
if (length % pieceSize != 0) if (length % rawPieceSize != 0)
rv++; rv++;
return rv; return rv;
} }

View File

@@ -1,5 +1,5 @@
group = com.muwire group = com.muwire
version = 0.3.8 version = 0.3.9
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

View File

@@ -44,6 +44,8 @@ class MainFrameController {
search = search.trim() search = search.trim()
if (search.length() == 0) if (search.length() == 0)
return return
if (search.length() > 128)
search = search.substring(0,128)
def uuid = UUID.randomUUID() def uuid = UUID.randomUUID()
Map<String, Object> params = new HashMap<>() Map<String, Object> params = new HashMap<>()
params["search-terms"] = search params["search-terms"] = search

View File

@@ -5,6 +5,7 @@ import griffon.core.controller.ControllerAction
import griffon.inject.MVCMember import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor import griffon.metadata.ArtifactProviderFor
import javax.annotation.Nonnull import javax.annotation.Nonnull
import javax.swing.JFileChooser
import com.muwire.core.Core import com.muwire.core.Core
@@ -60,6 +61,9 @@ class OptionsController {
boolean shareDownloaded = view.shareDownloadedCheckbox.model.isSelected() boolean shareDownloaded = view.shareDownloadedCheckbox.model.isSelected()
model.shareDownloadedFiles = shareDownloaded model.shareDownloadedFiles = shareDownloaded
settings.shareDownloadedFiles = shareDownloaded settings.shareDownloadedFiles = shareDownloaded
String downloadLocation = model.downloadLocation
settings.downloadLocation = new File(downloadLocation)
File settingsFile = new File(core.home, "MuWire.properties") File settingsFile = new File(core.home, "MuWire.properties")
settingsFile.withOutputStream { settingsFile.withOutputStream {
@@ -110,4 +114,15 @@ class OptionsController {
view.d.setVisible(false) view.d.setVisible(false)
mvcGroup.destroy() mvcGroup.destroy()
} }
@ControllerAction
void downloadLocation() {
def chooser = new JFileChooser()
chooser.setFileHidingEnabled(false)
chooser.setDialogTitle("Select location for downloaded files")
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
int rv = chooser.showOpenDialog(null)
if (rv == JFileChooser.APPROVE_OPTION)
model.downloadLocation = chooser.getSelectedFile().getAbsolutePath()
}
} }

View File

@@ -43,6 +43,8 @@ class Initialize extends AbstractLifecycleHandler {
application.context.put("muwire-home", home.getAbsolutePath()) application.context.put("muwire-home", home.getAbsolutePath())
System.getProperties().setProperty("awt.useSystemAAFontSettings", "true")
def guiPropsFile = new File(home, "gui.properties") def guiPropsFile = new File(home, "gui.properties")
UISettings uiSettings UISettings uiSettings
if (guiPropsFile.exists()) { if (guiPropsFile.exists()) {

View File

@@ -74,6 +74,7 @@ class Ready extends AbstractLifecycleHandler {
props.downloadLocation = new File(portableDownloads) props.downloadLocation = new File(portableDownloads)
} else { } else {
def chooser = new JFileChooser() def chooser = new JFileChooser()
chooser.setFileHidingEnabled(false)
chooser.setDialogTitle("Select a directory where downloads will be saved") chooser.setDialogTitle("Select a directory where downloads will be saved")
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
int rv = chooser.showOpenDialog(null) int rv = chooser.showOpenDialog(null)

View File

@@ -17,6 +17,7 @@ import com.muwire.core.connection.ConnectionEvent
import com.muwire.core.connection.DisconnectionEvent import com.muwire.core.connection.DisconnectionEvent
import com.muwire.core.download.DownloadStartedEvent import com.muwire.core.download.DownloadStartedEvent
import com.muwire.core.download.Downloader import com.muwire.core.download.Downloader
import com.muwire.core.files.AllFilesLoadedEvent
import com.muwire.core.files.FileDownloadedEvent import com.muwire.core.files.FileDownloadedEvent
import com.muwire.core.files.FileHashedEvent import com.muwire.core.files.FileHashedEvent
import com.muwire.core.files.FileLoadedEvent import com.muwire.core.files.FileLoadedEvent
@@ -139,6 +140,7 @@ class MainFrameModel {
core.eventBus.register(FileDownloadedEvent.class, this) core.eventBus.register(FileDownloadedEvent.class, this)
core.eventBus.register(FileUnsharedEvent.class, this) core.eventBus.register(FileUnsharedEvent.class, this)
core.eventBus.register(RouterDisconnectedEvent.class, this) core.eventBus.register(RouterDisconnectedEvent.class, this)
core.eventBus.register(AllFilesLoadedEvent.class, this)
timer.schedule({ timer.schedule({
if (core.shutdown.get()) if (core.shutdown.get())
@@ -167,9 +169,6 @@ class MainFrameModel {
trusted.addAll(core.trustService.good.values()) trusted.addAll(core.trustService.good.values())
distrusted.addAll(core.trustService.bad.values()) distrusted.addAll(core.trustService.bad.values())
watched.addAll(core.muOptions.watchedDirectories)
builder.getVariable("watched-directories-table").model.fireTableDataChanged()
watched.each { core.eventBus.publish(new FileSharedEvent(file : new File(it))) }
resumeButtonText = "Retry" resumeButtonText = "Retry"
} }
@@ -177,6 +176,13 @@ class MainFrameModel {
} }
void onAllFilesLoadedEvent(AllFilesLoadedEvent e) {
runInsideUIAsync {
watched.addAll(core.muOptions.watchedDirectories)
builder.getVariable("watched-directories-table").model.fireTableDataChanged()
watched.each { core.eventBus.publish(new FileSharedEvent(file : new File(it))) }
}
}
void onUIResultEvent(UIResultEvent e) { void onUIResultEvent(UIResultEvent e) {
MVCGroup resultsGroup = results.get(e.uuid) MVCGroup resultsGroup = results.get(e.uuid)
resultsGroup?.model.handleResult(e) resultsGroup?.model.handleResult(e)

View File

@@ -13,6 +13,7 @@ class OptionsModel {
@Observable String updateCheckInterval @Observable String updateCheckInterval
@Observable boolean onlyTrusted @Observable boolean onlyTrusted
@Observable boolean shareDownloadedFiles @Observable boolean shareDownloadedFiles
@Observable String downloadLocation
// i2p options // i2p options
@Observable String inboundLength @Observable String inboundLength
@@ -35,6 +36,7 @@ class OptionsModel {
updateCheckInterval = settings.updateCheckInterval updateCheckInterval = settings.updateCheckInterval
onlyTrusted = !settings.allowUntrusted() onlyTrusted = !settings.allowUntrusted()
shareDownloadedFiles = settings.shareDownloadedFiles shareDownloadedFiles = settings.shareDownloadedFiles
downloadLocation = settings.downloadLocation.getAbsolutePath()
Core core = application.context.get("core") Core core = application.context.get("core")
inboundLength = core.i2pOptions["inbound.length"] inboundLength = core.i2pOptions["inbound.length"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -21,10 +21,10 @@ class EventListView {
application(size: [320, 80], id: 'event-list', application(size: [320, 80], id: 'event-list',
locationRelativeTo : null, locationRelativeTo : null,
title: application.configuration['application.title'], title: application.configuration['application.title'],
iconImage: imageIcon('/griffon-icon-48x48.png').image, iconImage: imageIcon('/MuWire-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image, iconImages: [imageIcon('/MuWire-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image, imageIcon('/MuWire-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image], imageIcon('/MuWire-16x16.png').image],
visible: bind { !model.coreInitialized} ) { visible: bind { !model.coreInitialized} ) {
panel { panel {
vbox { vbox {

View File

@@ -60,10 +60,10 @@ class MainFrameView {
locationRelativeTo : null, locationRelativeTo : null,
title: application.configuration['application.title'] + " " + title: application.configuration['application.title'] + " " +
metadata["application.version"] + " revision " + metadata["build.revision"], metadata["application.version"] + " revision " + metadata["build.revision"],
iconImage: imageIcon('/griffon-icon-48x48.png').image, iconImage: imageIcon('/MuWire-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image, iconImages: [imageIcon('/MuWire-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image, imageIcon('/MuWire-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image], imageIcon('/MuWire-16x16.png').image],
pack : false, pack : false,
visible : bind { model.coreInitialized }) { visible : bind { model.coreInitialized }) {
menuBar { menuBar {
@@ -185,11 +185,14 @@ class MainFrameView {
closureColumn(header : "Name", type : String, read : {row -> row.getName() }) closureColumn(header : "Name", type : String, read : {row -> row.getName() })
closureColumn(header : "Progress", type : String, read : { row -> closureColumn(header : "Progress", type : String, read : { row ->
int percent = row.getProgress() int percent = row.getProgress()
"$percent%" "$percent% of piece".toString()
}) })
closureColumn(header : "Downloader", type : String, read : { row -> closureColumn(header : "Downloader", type : String, read : { row ->
row.getDownloader() row.getDownloader()
}) })
closureColumn(header : "Remote Pieces", type : String, read : { row ->
"${row.getDonePieces()}/${row.getTotalPieces()}".toString()
})
} }
} }
} }
@@ -516,6 +519,7 @@ class MainFrameView {
def shareFiles = { def shareFiles = {
def chooser = new JFileChooser() def chooser = new JFileChooser()
chooser.setFileHidingEnabled(false)
chooser.setDialogTitle("Select file to share") chooser.setDialogTitle("Select file to share")
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY) chooser.setFileSelectionMode(JFileChooser.FILES_ONLY)
int rv = chooser.showOpenDialog(null) int rv = chooser.showOpenDialog(null)
@@ -526,6 +530,7 @@ class MainFrameView {
def watchDirectories = { def watchDirectories = {
def chooser = new JFileChooser() def chooser = new JFileChooser()
chooser.setFileHidingEnabled(false)
chooser.setDialogTitle("Select directory to watch") chooser.setDialogTitle("Select directory to watch")
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
int rv = chooser.showOpenDialog(null) int rv = chooser.showOpenDialog(null)

View File

@@ -68,6 +68,10 @@ class OptionsView {
label(text : "Share downloaded files", constraints : gbc(gridx : 0, gridy:3)) label(text : "Share downloaded files", constraints : gbc(gridx : 0, gridy:3))
shareDownloadedCheckbox = checkBox(selected : bind {model.shareDownloadedFiles}, constraints : gbc(gridx :1, gridy:3)) shareDownloadedCheckbox = checkBox(selected : bind {model.shareDownloadedFiles}, constraints : gbc(gridx :1, gridy:3))
label(text : "Save downloaded files to:", constraints: gbc(gridx:0, gridy:4))
button(text : "Choose", constraints : gbc(gridx : 1, gridy:4), downloadLocationAction)
label(text : bind {model.downloadLocation}, constraints: gbc(gridx:0, gridy:5, gridwidth:2))
} }
i = builder.panel { i = builder.panel {

View File

@@ -26,7 +26,7 @@ handlers= java.util.logging.FileHandler
# can be overriden by a facility specific level # can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level # Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console. # setting to limit messages printed to the console.
.level= SEVERE .level= INFO
############################################################ ############################################################
# Handler specific properties. # Handler specific properties.