Compare commits

...

13 Commits

20 changed files with 632 additions and 70 deletions

View File

@ -32,7 +32,7 @@ import com.muwire.core.UILoadedEvent
import com.muwire.core.files.AllFilesLoadedEvent
class CliLanterna {
private static final String MW_VERSION = "0.6.15"
private static final String MW_VERSION = "0.7.0"
private static volatile Core core

View File

@ -165,9 +165,9 @@ public class Core {
i2pOptionsFile.withInputStream { i2pOptions.load(it) }
if (!i2pOptions.containsKey("inbound.nickname"))
i2pOptions["inbound.nickname"] = tunnelName
i2pOptions["inbound.nickname"] = "MuWire"
if (!i2pOptions.containsKey("outbound.nickname"))
i2pOptions["outbound.nickname"] = tunnelName
i2pOptions["outbound.nickname"] = "MuWire"
}
if (!(i2pOptions.containsKey("i2np.ntcp.port")
&& i2pOptions.containsKey("i2np.udp.port")
@ -178,6 +178,8 @@ public class Core {
i2pOptions["i2np.udp.port"] = String.valueOf(port)
i2pOptionsFile.withOutputStream { i2pOptions.store(it, "") }
}
i2pOptions['i2cp.leaseSetEncType']='4,0'
if (!props.embeddedRouter) {
if (!(I2PAppContext.getGlobalContext() instanceof RouterContext)) {
@ -544,7 +546,7 @@ public class Core {
}
}
Core core = new Core(props, home, "0.6.15")
Core core = new Core(props, home, "0.7.0")
core.startServices()
// ... at the end, sleep or execute script

View File

@ -1,6 +1,6 @@
group = com.muwire
version = 0.6.15
i2pVersion = 0.9.45
version = 0.7.0
i2pVersion = 0.9.46
groovyVersion = 2.4.15
slf4jVersion = 1.7.25
spockVersion = 1.1-groovy-2.4

View File

@ -141,4 +141,9 @@ mvcGroups {
view = 'com.muwire.gui.SignView'
controller = 'com.muwire.gui.SignController'
}
'wizard' {
model = 'com.muwire.gui.wizard.WizardModel'
view = 'com.muwire.gui.wizard.WizardView'
controller = 'com.muwire.gui.wizard.WizardController'
}
}

View File

@ -32,22 +32,14 @@ class OptionsController {
def i2pProps = core.i2pOptions
text = view.inboundLengthField.text
model.inboundLength = text
i2pProps["inbound.length"] = text
text = view.inboundQuantityField.text
model.inboundQuantity = text
i2pProps["inbound.quantity"] = text
text = view.outboundQuantityField.text
model.outboundQuantity = text
i2pProps["outbound.quantity"] = text
text = view.outboundLengthField.text
model.outboundLength = text
i2pProps["outbound.length"] = text
int tunnelLength = view.tunnelLengthSlider.value
i2pProps["inbound.length"] = String.valueOf(tunnelLength)
i2pProps["outbound.length"] = String.valueOf(tunnelLength)
int tunnelQuantity = view.tunnelQuantitySlider.value
i2pProps["inbound.quantity"] = String.valueOf(tunnelQuantity)
i2pProps["outbound.quantity"] = String.valueOf(tunnelQuantity)
if (settings.embeddedRouter) {
text = view.i2pNTCPPortField.text
model.i2pNTCPPort = text

View File

@ -0,0 +1,49 @@
package com.muwire.gui.wizard
import griffon.core.artifact.GriffonController
import griffon.core.controller.ControllerAction
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import javax.annotation.Nonnull
import javax.swing.JOptionPane
@ArtifactProviderFor(GriffonController)
class WizardController {
@MVCMember @Nonnull
WizardModel model
@MVCMember @Nonnull
WizardView view
@ControllerAction
void previous() {
model.currentStep--
view.updateLayout()
}
@ControllerAction
void next() {
def errors = model.steps[model.currentStep].validate()
if (errors != null && !errors.isEmpty()) {
String errorMessage = String.join("\n", errors)
JOptionPane.showMessageDialog(model.parent, errorMessage, "Invalid Input", JOptionPane.ERROR_MESSAGE)
} else {
model.currentStep++
view.updateLayout()
}
}
@ControllerAction
void finish() {
model.steps.each {
it.apply(model.muSettings, model.i2pProps)
}
model.finished['applied'] = true
view.hide()
}
@ControllerAction
void cancel() {
model.finished['applied'] = false
view.hide()
}
}

View File

@ -54,28 +54,33 @@ class Ready extends AbstractLifecycleHandler {
} else {
log.info("creating new properties")
props = new MuWireSettings()
props.incompleteLocation = new File(home, "incompletes")
props.embeddedRouter = Boolean.parseBoolean(System.getProperties().getProperty("embeddedRouter"))
props.updateType = System.getProperty("updateType","jar")
props.setNickname(selectNickname())
def portableDownloads = System.getProperty("portable.downloads")
if (portableDownloads != null) {
props.downloadLocation = new File(portableDownloads)
} else {
def chooser = new JFileChooser()
chooser.setFileHidingEnabled(false)
chooser.setDialogTitle("Select a directory where downloads will be saved")
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
int rv = chooser.showOpenDialog(null)
if (rv != JFileChooser.APPROVE_OPTION) {
JOptionPane.showMessageDialog(null, "MuWire will now exit")
System.exit(0)
}
props.downloadLocation = chooser.getSelectedFile()
boolean embeddedRouterAvailable = Boolean.parseBoolean(System.getProperties().getProperty("embeddedRouter"))
def parent = application.windowManager.findWindow("event-list")
Properties i2pProps = new Properties()
def params = [:]
params['parent'] = parent
params['embeddedRouterAvailable'] = embeddedRouterAvailable
params['muSettings'] = props
params['i2pProps'] = i2pProps
def finished = [:]
params['finished'] = finished
application.mvcGroupManager.createMVCGroup("wizard", params)
if (!finished['applied']) {
JOptionPane.showMessageDialog(parent, "MuWire will now exit")
System.exit(0)
}
File i2pPropsFile = new File(home, "i2p.properties")
i2pPropsFile.withPrintWriter { i2pProps.store(it, "") }
props.embeddedRouter = embeddedRouterAvailable
props.updateType = System.getProperty("updateType","jar")
propsFile.withPrintWriter("UTF-8", {
props.write(it)
})

View File

@ -25,10 +25,8 @@ class OptionsModel {
@Observable boolean storeSearchHistory
// i2p options
@Observable String inboundLength
@Observable String inboundQuantity
@Observable String outboundLength
@Observable String outboundQuantity
@Observable int tunnelLength
@Observable int tunnelQuantity
@Observable String i2pUDPPort
@Observable String i2pNTCPPort
@ -90,10 +88,8 @@ class OptionsModel {
uploadSlotsPerUser = settings.uploadSlotsPerUser
Core core = application.context.get("core")
inboundLength = core.i2pOptions["inbound.length"]
inboundQuantity = core.i2pOptions["inbound.quantity"]
outboundLength = core.i2pOptions["outbound.length"]
outboundQuantity = core.i2pOptions["outbound.quantity"]
tunnelLength = Math.max(Integer.parseInt(core.i2pOptions["inbound.length"]), Integer.parseInt(core.i2pOptions['outbound.length']))
tunnelQuantity = Math.max(Integer.parseInt(core.i2pOptions["inbound.quantity"]), Integer.parseInt(core.i2pOptions['outbound.quantity']))
i2pUDPPort = core.i2pOptions["i2np.udp.port"]
i2pNTCPPort = core.i2pOptions["i2np.ntcp.port"]

View File

@ -0,0 +1,42 @@
package com.muwire.gui.wizard
import java.awt.Component
import com.muwire.core.MuWireSettings
import griffon.core.artifact.GriffonModel
import griffon.transform.Observable
import griffon.metadata.ArtifactProviderFor
@ArtifactProviderFor(GriffonModel)
class WizardModel {
Component parent
boolean embeddedRouterAvailable
MuWireSettings muSettings
Properties i2pProps
def finished
final List<WizardStep> steps = []
int currentStep
@Observable boolean finishButtonEnabled
@Observable boolean previousButtonEnabled
@Observable boolean nextButtonEnabled
void mvcGroupInit(Map<String,String> args) {
steps << new NicknameStep()
steps << new DirectoriesStep()
if (embeddedRouterAvailable)
steps << new EmbeddedRouterStep()
else
steps << new ExternalRouterStep()
steps << new TunnelStep()
steps << new LastStep(embeddedRouterAvailable)
currentStep = 0
previousButtonEnabled = false
nextButtonEnabled = steps.size() > (currentStep + 1)
finishButtonEnabled = steps.size() == currentStep + 1
}
}

View File

@ -6,7 +6,9 @@ import griffon.metadata.ArtifactProviderFor
import groovy.swing.factory.TitledBorderFactory
import javax.swing.JDialog
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.JSlider
import javax.swing.JTabbedPane
import javax.swing.SwingConstants
import javax.swing.border.TitledBorder
@ -48,10 +50,8 @@ class OptionsView {
def totalUploadSlotsField
def uploadSlotsPerUserField
def inboundLengthField
def inboundQuantityField
def outboundLengthField
def outboundQuantityField
def tunnelLengthSlider
def tunnelQuantitySlider
def i2pUDPPortField
def i2pNTCPPortField
@ -168,19 +168,24 @@ class OptionsView {
label(text : "Changing any I2P settings requires a restart", constraints : gbc(gridx:0, gridy : 0))
panel (border : titledBorder(title : "Tunnel Settings", border : etchedBorder(), titlePosition: TitledBorder.TOP,
constraints : gbc(gridx: 0, gridy: 1, fill : GridBagConstraints.HORIZONTAL, weightx : 100))) {
gridBagLayout()
label(text : "Inbound length", constraints : gbc(gridx:0, gridy:0, anchor : GridBagConstraints.LINE_START, weightx : 100))
inboundLengthField = textField(text : bind {model.inboundLength}, columns : 2, constraints : gbc(gridx:1, gridy:0,
anchor : GridBagConstraints.LINE_END))
label(text : "Inbound quantity", constraints : gbc(gridx:0, gridy:1, anchor : GridBagConstraints.LINE_START, weightx : 100))
inboundQuantityField = textField(text : bind {model.inboundQuantity}, columns : 2, constraints : gbc(gridx:1, gridy:1,
anchor : GridBagConstraints.LINE_END))
label(text : "Outbound length", constraints : gbc(gridx:0, gridy:2, anchor : GridBagConstraints.LINE_START, weightx : 100))
outboundLengthField = textField(text : bind {model.outboundLength}, columns : 2, constraints : gbc(gridx:1, gridy:2,
anchor : GridBagConstraints.LINE_END))
label(text : "Outbound quantity", constraints : gbc(gridx:0, gridy:3, anchor : GridBagConstraints.LINE_START, weightx : 100))
outboundQuantityField = textField(text : bind {model.outboundQuantity}, columns : 2, constraints : gbc(gridx:1, gridy:3,
anchor : GridBagConstraints.LINE_END))
gridLayout(rows:4, cols:1)
label(text : "Speed vs Anonymity")
def lengthTable = new Hashtable()
lengthTable.put(1, new JLabel("Max Speed"))
lengthTable.put(3, new JLabel("Max Anonymity"))
tunnelLengthSlider = slider(minimum : 1, maximum : 3, value : bind {model.tunnelLength},
majorTickSpacing : 1, snapToTicks: true, paintTicks: true, labelTable : lengthTable,
paintLabels : true)
label(text: "Reliability vs Resource Usage")
def quantityTable = new Hashtable()
quantityTable.put(1, new JLabel("Min Resources"))
quantityTable.put(6, new JLabel("Max Reliability"))
tunnelQuantitySlider = slider(minimum : 1, maximum : 6, value : bind {model.tunnelQuantity},
majorTickSpacing : 1, snapToTicks : true, paintTicks: true, labelTable : quantityTable,
paintLabels : true)
}
Core core = application.context.get("core")

View File

@ -0,0 +1,78 @@
package com.muwire.gui.wizard
import griffon.core.artifact.GriffonView
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import javax.swing.JDialog
import javax.swing.SwingConstants
import java.awt.BorderLayout
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import javax.annotation.Nonnull
@ArtifactProviderFor(GriffonView)
class WizardView {
@MVCMember @Nonnull
FactoryBuilderSupport builder
@MVCMember @Nonnull
WizardModel model
def dialog
def p
void initUI() {
dialog = new JDialog(model.parent, "Setup Wizard", true)
p = builder.panel {
borderLayout()
panel (id : "cards-panel", constraints : BorderLayout.CENTER) {
cardLayout()
model.steps.each {
it.buildUI(builder)
}
}
panel (constraints : BorderLayout.SOUTH) {
gridLayout(rows:1, cols:2)
panel {
button(text : "Cancel", cancelAction)
}
panel {
button(text : "Previous", enabled : bind {model.previousButtonEnabled}, previousAction)
button(text : "Next", enabled : bind {model.nextButtonEnabled}, nextAction)
button(text : "Finish", enabled : bind {model.finishButtonEnabled}, finishAction)
}
}
}
}
void updateLayout() {
model.previousButtonEnabled = model.currentStep > 0
model.nextButtonEnabled = model.steps.size() > (model.currentStep + 1)
model.finishButtonEnabled = model.steps.size() == (model.currentStep + 1)
String constraints = model.steps[model.currentStep].getConstraint()
def cardsPanel = builder.getVariable("cards-panel")
cardsPanel.getLayout().show(cardsPanel, constraints)
}
void mvcGroupInit(Map<String,String> args) {
dialog.getContentPane().add(p)
dialog.pack()
dialog.setLocationRelativeTo(model.parent)
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
dialog.addWindowListener( new WindowAdapter() {
public void windowClosed(WindowEvent e) {
mvcGroup.destroy()
}
})
dialog.show()
}
void hide() {
dialog.setVisible(false)
mvcGroup.destroy()
}
}

View File

@ -0,0 +1,92 @@
package com.muwire.gui.wizard
import java.awt.GridBagConstraints
import javax.swing.JFileChooser
import com.muwire.core.MuWireSettings
class DirectoriesStep extends WizardStep {
def downloadLocationField
def incompleteLocationField
def downloadLocationButton
def incompleteLocationButton
public DirectoriesStep(String constraint) {
super("directories")
}
@Override
protected void buildUI(FactoryBuilderSupport builder) {
File defaultDownloadLocation = new File(System.getProperty("user.home"), "MuWire Downloads")
File defaultIncompleteLocation = new File(System.getProperty("user.home"), "MuWire Incompletes")
builder.panel(constraints : getConstraint()) {
gridBagLayout()
label(text : "Select directories for saving downloaded and incomplete files.",
constraints : gbc(gridx: 0, gridy: 0, gridwidth : 2, insets: [10,0,0,0]))
label(text : "They will be created if they do not already exist.",
constraints : gbc(gridx:0, gridy: 1, gridwidth: 2, insets: [0,0,10,0]))
label(text : "Directory for saving downloaded files", constraints : gbc(gridx:0, gridy: 2))
downloadLocationField = textField(text : defaultDownloadLocation.getAbsolutePath(),
constraints : gbc(gridx : 0, gridy : 3, fill : GridBagConstraints.HORIZONTAL, weightx: 100))
downloadLocationButton = button(text : "Choose", constraints : gbc(gridx: 1, gridy: 3), actionPerformed : showDownloadChooser)
label(text : "Directory for storing incomplete files", constraints : gbc(gridx:0, gridy: 4))
incompleteLocationField = textField(text : defaultIncompleteLocation.getAbsolutePath(),
constraints : gbc(gridx:0, gridy:5, fill : GridBagConstraints.HORIZONTAL, weightx: 100))
incompleteLocationButton = button(text : "Choose", constraints : gbc(gridx: 1, gridy: 5), actionPerformed : showIncompleteChooser)
}
}
@Override
protected List<String> validate() {
def rv = []
if (!canWrite(downloadLocationField.text))
rv << "Download location not writeable"
if (!canWrite(incompleteLocationField.text))
rv << "Incomplete location not writeable"
rv
}
private static boolean canWrite(String location) {
File f = new File(location)
if (f.exists())
return f.isDirectory() && f.canWrite()
canWrite(f.getParentFile().getAbsolutePath())
}
@Override
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
muSettings.downloadLocation = new File(downloadLocationField.text)
muSettings.incompleteLocation = new File(incompleteLocationField.text)
muSettings.downloadLocation.mkdirs()
muSettings.incompleteLocation.mkdirs()
}
def showDownloadChooser = {
String text = chooseFile("Select directory for downloaded files")
if (text != null)
downloadLocationField.text = text
}
def showIncompleteChooser = {
String text = chooseFile("Select directory for incomplete files")
if (text != null)
incompleteLocationField.text = text
}
private String chooseFile(String title) {
def chooser = new JFileChooser()
chooser.setFileHidingEnabled(false)
chooser.setDialogTitle(title)
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
int rv = chooser.showOpenDialog(null)
if (rv == JFileChooser.APPROVE_OPTION)
return chooser.getSelectedFile().getAbsolutePath()
else
return null
}
}

View File

@ -0,0 +1,82 @@
package com.muwire.gui.wizard
import java.awt.GridBagConstraints
import javax.swing.border.TitledBorder
import com.muwire.core.MuWireSettings
class EmbeddedRouterStep extends WizardStep {
def udpPortField
def tcpPortField
def inBwField
def outBwField
public EmbeddedRouterStep() {
super("router")
}
@Override
protected void buildUI(FactoryBuilderSupport builder) {
Random r = new Random()
int port = 9151 + r.nextInt(1 + 30777 - 9151) // this range matches what the i2p router would choose
builder.panel(constraints : getConstraint()) {
gridBagLayout()
panel(border : titledBorder(title : "Port Settings", border : etchedBorder(), titlePosition : TitledBorder.TOP,
constraints : gbc(gridx: 0, gridy : 0, fill : GridBagConstraints.HORIZONTAL, weightx: 100))) {
gridBagLayout()
label(text : "TCP port", constraints : gbc(gridx :0, gridy: 0, anchor : GridBagConstraints.LINE_START, weightx : 100))
tcpPortField = textField(text : String.valueOf(port), columns : 4, constraints : gbc(gridx:1, gridy:0, anchor : GridBagConstraints.LINE_END))
label(text : "UDP port", constraints : gbc(gridx :0, gridy: 1, anchor : GridBagConstraints.LINE_START, weightx : 100))
udpPortField = textField(text : String.valueOf(port), columns : 4, constraints : gbc(gridx:1, gridy:1, anchor : GridBagConstraints.LINE_END))
}
panel( border : titledBorder(title : "Bandwidth Settings", border : etchedBorder(), titlePosition : TitledBorder.TOP),
constraints : gbc(gridx : 0, gridy : 1, fill : GridBagConstraints.HORIZONTAL, weightx : 100)) {
gridBagLayout()
label(text : "Inbound bandwidth (KB)", constraints : gbc(gridx: 0, gridy : 0, anchor : GridBagConstraints.LINE_START, weightx : 100))
inBwField = textField(text : "512", columns : 3, constraints : gbc(gridx : 1, gridy : 0, anchor : GridBagConstraints.LINE_END))
label(text : "Outbound bandwidth (KB)", constraints : gbc(gridx: 0, gridy : 1, anchor : GridBagConstraints.LINE_START, weightx : 100))
outBwField = textField(text : "256", columns : 3, constraints : gbc(gridx : 1, gridy : 1, anchor : GridBagConstraints.LINE_END))
}
panel (constraints : gbc(gridx: 0, gridy : 2, weighty: 100))
}
}
@Override
protected List<String> validate() {
def rv = []
try {
int udpPort = Integer.parseInt(udpPortField.text)
int tcpPort = Integer.parseInt(tcpPortField.text)
if (udpPort <= 0 || udpPort > 0xFFFF)
rv << "Invalid UDP Port"
if (tcpPort <= 0 || tcpPort > 0xFFFF)
rv << "Invalid TCP Port"
} catch (NumberFormatException e) {
rv << "Invalid port"
}
try {
int outBw = Integer.parseInt(outBwField.text)
int inBw = Integer.parseInt(inBwField.text)
if (outBw <= 0)
rv << "Out bandwidth cannot be negative"
if (inBw <= 0)
rv << "In bandwidth cannot be ngative"
} catch (NumberFormatException e) {
rv << "Invalid bandwidth"
}
rv
}
@Override
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
i2pSettings['i2np.ntcp.port'] = tcpPortField.text
i2pSettings['i2np.udp.port'] = udpPortField.text
muSettings.outBw = Integer.parseInt(outBwField.text)
muSettings.inBw = Integer.parseInt(inBwField.text)
}
}

View File

@ -0,0 +1,59 @@
package com.muwire.gui.wizard
import java.awt.GridBagConstraints
import javax.swing.border.TitledBorder
import com.muwire.core.MuWireSettings
class ExternalRouterStep extends WizardStep {
def addressField
def portField
public ExternalRouterStep() {
super("router")
}
@Override
protected void buildUI(FactoryBuilderSupport builder) {
builder.panel(constraints : getConstraint()) {
gridBagLayout()
panel(border : titledBorder(title : "External Router I2CP Settings", border : etchedBorder(), titlePosition : TitledBorder.TOP,
constraints : gbc(gridx: 0, gridy : 0, fill : GridBagConstraints.HORIZONTAL, weightx: 100))) {
gridBagLayout()
label(text : "Host", constraints : gbc(gridx: 0, gridy : 0, anchor : GridBagConstraints.LINE_START, weightx : 100))
addressField = textField(text : "127.0.0.1", constraints : gbc(gridx:1, gridy:0, anchor: GridBagConstraints.LINE_END))
label(text : "Port", constraints : gbc(gridx: 0, gridy : 1, anchor : GridBagConstraints.LINE_START, weightx : 100))
portField = textField(text : "7654", constraints : gbc(gridx:1, gridy:1, anchor: GridBagConstraints.LINE_END))
}
panel(constraints : gbc(gridx:0, gridy:1, weighty: 100))
}
}
@Override
protected List<String> validate() {
def rv = []
try {
InetAddress.getAllByName(addressField.text)
} catch (UnknownHostException iox) {
rv << "Not a valid InetAddress"
}
try {
int port = Integer.parseInt(portField.text)
if (port <= 0 && port > 0xFFFF)
rv << "Not a valid port"
} catch (NumberFormatException e) {
rv << "Not a valid port"
}
rv
}
@Override
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
i2pSettings['i2cp.tcp.host'] = addressField.text
i2pSettings['i2cp.tcp.port'] = portField.text
}
}

View File

@ -0,0 +1,32 @@
package com.muwire.gui.wizard
import com.muwire.core.MuWireSettings
class LastStep extends WizardStep {
private final boolean embeddedRouterAvailable
public LastStep(boolean embeddedRouterAvailable) {
super("last")
this.embeddedRouterAvailable = embeddedRouterAvailable
}
@Override
protected void buildUI(FactoryBuilderSupport builder) {
builder.panel(constraints: getConstraint()) {
gridBagLayout()
label(text: "The wizard is complete. Press \"Finish\" to launch MuWire.", constraints : gbc(gridx: 0, gridy: 0))
if (embeddedRouterAvailable)
label(text : "MuWire will launch an embedded I2P router. This can take a few minutes.", constraints: gbc(gridx:0, gridy:1))
}
}
@Override
protected List<String> validate() {
return null
}
@Override
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
}
}

View File

@ -0,0 +1,40 @@
package com.muwire.gui.wizard
import com.muwire.core.Constants
import com.muwire.core.MuWireSettings
import com.muwire.core.util.DataUtil
class NicknameStep extends WizardStep {
volatile def nickField
public NicknameStep() {
super("nickname")
}
@Override
protected void buildUI(FactoryBuilderSupport builder) {
builder.panel(constraints : getConstraint()) {
label(text: "Select a nickname")
nickField = textField(columns: 30)
}
}
@Override
protected List<String> validate() {
String nickname = nickField.text
if (nickname == null)
return ['Please select a nickname']
nickname = nickname.trim()
if (nickname.length() == 0)
return ['Nickname cannot be blank']
if (!DataUtil.isValidName(nickname))
return ["Nickname cannot contain any of ${Constants.INVALID_NICKNAME_CHARS} and must be no longer than ${Constants.MAX_NICKNAME_LENGTH} characters. Choose another."]
null
}
@Override
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
muSettings.nickname = nickField.text.trim()
}
}

View File

@ -0,0 +1,61 @@
package com.muwire.gui.wizard
import java.awt.GridBagConstraints
import javax.swing.JLabel
import javax.swing.border.TitledBorder
import com.muwire.core.MuWireSettings
class TunnelStep extends WizardStep {
def tunnelLengthSlider
def tunnelQuantitySlider
public TunnelStep() {
super("tunnels")
}
@Override
protected void buildUI(FactoryBuilderSupport builder) {
builder.panel (constraints : getConstraint()) {
gridBagLayout()
panel (border : titledBorder(title : "Speed vs. Anonymity", border : etchedBorder(), titlePosition: TitledBorder.TOP,
constraints : gbc(gridx: 0, gridy: 0, fill : GridBagConstraints.HORIZONTAL, weightx : 100))) {
def lengthTable = new Hashtable()
lengthTable.put(1, new JLabel("Max Speed"))
lengthTable.put(3, new JLabel("Max Anonymity"))
tunnelLengthSlider = slider(minimum : 1, maximum : 3, value : 3,
majorTickSpacing : 1, snapToTicks: true, paintTicks: true, labelTable : lengthTable,
paintLabels : true)
}
panel (border : titledBorder(title : "Reliability vs. Resource Usage", border : etchedBorder(), titlePosition: TitledBorder.TOP,
constraints : gbc(gridx: 0, gridy: 1, fill : GridBagConstraints.HORIZONTAL, weightx : 100))) {
def quantityTable = new Hashtable()
quantityTable.put(1, new JLabel("Min Resources"))
quantityTable.put(6, new JLabel("Max Reliability"))
tunnelQuantitySlider = slider(minimum : 1, maximum : 6, value : 4,
majorTickSpacing : 1, snapToTicks : true, paintTicks: true, labelTable : quantityTable,
paintLabels : true)
}
panel(constraints : gbc(gridx:0, gridy: 2, weighty: 100))
}
}
@Override
protected List<String> validate() {
return null
}
@Override
protected void apply(MuWireSettings muSettings, Properties i2pSettings) {
String tunnelLength = String.valueOf(tunnelLengthSlider.value)
i2pSettings['inbound.length'] = tunnelLength
i2pSettings['outbound.length'] = tunnelLength
String tunnelQuantity = tunnelQuantitySlider.value
i2pSettings['inbound.quantity'] = tunnelQuantity
i2pSettings['outbound.quantity'] = tunnelQuantity
}
}

View File

@ -0,0 +1,22 @@
package com.muwire.gui.wizard
import com.muwire.core.MuWireSettings
abstract class WizardStep {
final String constraint
protected WizardStep(String constraint) {
this.constraint = constraint
}
protected abstract void buildUI(FactoryBuilderSupport builder)
/**
* @return list of errors, null if validation is successful
*/
protected abstract List<String> validate()
protected abstract void apply(MuWireSettings muSettings, Properties i2pSettings)
}

View File

@ -48,7 +48,7 @@ public class SearchServlet extends HttpServlet {
if (newUUID != null)
resp.sendRedirect("/MuWire/Home?uuid=" + newUUID.toString());
else
resp.sendError(403, Util._t("Please enter a search keyword or hash"));
resp.sendError(403, Util._t("Please enter a search keyword or file hash"));
} else if (action.equals("stop")) {
String uuidString = req.getParameter("uuid");
UUID uuid = UUID.fromString(uuidString);

View File

@ -5,7 +5,7 @@
<%
String pagetitle=Util._t("Subscriptions");
String helptext = Util._t("This page shows the trust lists of the users you have subscribed to.");
String helptext = Util._t("This page shows the trust lists you are subscribed to.");
%>
<html>