Skip to content

Commit

Permalink
✨feature: ui and function enhance
Browse files Browse the repository at this point in the history
  • Loading branch information
tom8zds committed Jul 7, 2024
1 parent 4bf828e commit 4370689
Show file tree
Hide file tree
Showing 35 changed files with 1,341 additions and 730 deletions.
27 changes: 26 additions & 1 deletion assets/i18n/strings.i18n.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
{
"appTitle": "RustSend",
"appTitle": {
"parta": "LocalSend",
"partb": "_RS"
},
"home": {
"title": "Home Page"
},
"mission": {
"accept": "Accept",
"cancel": "Cancel",
"complete": "Complete",
"finished": "Finished",
"tranfer": "Transfering",
"pending": "Pending",
"failed": "Failed",
"skip": "Skip",
"advance": "Advance"
},
"common": {
"file": "File",
"size": "Size"
},
"setting": {
"title": "Settings",
"common": "Common",
Expand All @@ -19,6 +37,13 @@
"title": "Language",
"subTitle": "Current language: $language"
},
"receive": {
"title": "Receive",
"quickSave": "Quick Save",
"quickSaveHint": "Start tranfer without accept",
"saveFolder": "Save Folder",
"selectSaveFolder": "Select"
},
"core": {
"title": "core setting",
"server": {
Expand Down
27 changes: 26 additions & 1 deletion assets/i18n/strings_zh.i18n.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
{
"appTitle": "锈船",
"appTitle": {
"parta": "快传",
"partb": ""
},
"home": {
"title": "主页"
},
"mission": {
"accept": "接收",
"cancel": "取消",
"complete": "完成",
"finished": "已完成",
"tranfer": "传输中",
"pending": "等待中",
"failed": "失败",
"skip": "跳过",
"advance": "高级"
},
"common": {
"file": "文件",
"size": "大小"
},
"setting": {
"title": "设置",
"common": "通用",
Expand All @@ -19,6 +37,13 @@
"title": "语言",
"subTitle": "当前语言: $language"
},
"receive": {
"title": "接收设置",
"quickSave": "快速保存",
"quickSaveHint": "不需要等待确认直接接受",
"saveFolder": "保存目录",
"selectSaveFolder": "选择"
},
"core": {
"title": "核心设置",
"server": {
Expand Down
2 changes: 1 addition & 1 deletion lib/common/device_info_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ int randomPort() {
return 10000 + Random().nextInt(65535 - 10000);
}

Future<NodeDevice> newDevice() async {
Future<NodeDevice> getDevice() async {
final deviceInfo = await getDeviceInfo();
final addressList = await getInterface();
final alias =
Expand Down
125 changes: 124 additions & 1 deletion lib/common/utils.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:localsend_rs/core/rust/actor/model.dart';
import 'package:localsend_rs/core/store/config_store.dart';
import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
import 'package:window_manager/window_manager.dart';

import '../core/rust/actor/core.dart';
import '../core/rust/actor/mission.dart';
import '../core/rust/bridge.dart';
import '../i18n/strings.g.dart';
import 'constants.dart';

Future<void> sleepAsync(int millis) {
return Future.delayed(Duration(milliseconds: millis), () {});
Expand Down Expand Up @@ -37,7 +49,7 @@ Future<void> updateSystemOverlayStyleWithBrightness(
}
}

Locale stringToLocale(String value){
Locale stringToLocale(String value) {
if (value.isEmpty) {
value = Platform.localeName;
}
Expand All @@ -60,3 +72,114 @@ Locale stringToLocale(String value){
}
return const Locale("en");
}

Future<CoreConfig> getConfig(int port) async {
if (!ConfigStore().storePathSet()) {
final path = await getDownloadPath();
ConfigStore().setStorePath(path);
}
final storePath = ConfigStore().storePath();

return CoreConfig(
port: port,
interfaceAddr: "0.0.0.0",
multicastAddr: "224.0.0.167",
multicastPort: 53317,
storePath: storePath,
);
}

Future<String> getDownloadPath() async {
String storePath;
if (Platform.isAndroid) {
storePath = "/storage/emulated/0/Download";
if (kDebugMode) {
createLogStream().listen((event) {
debugPrint(
'${event.level} ${event.tag} ${event.msg} ${event.timeMillis}');
});
}
} else {
storePath = (await getDownloadsDirectory())!.absolute.path;
}
return storePath;
}

const levelList = [
Level.off,
Level.error,
Level.warning,
Level.info,
Level.debug,
Level.trace
];

void initLogger() {
var logger = Logger();

if (Platform.isAndroid) {
if (kDebugMode) {
createLogStream().listen((event) {
logger.log(
levelList[event.level],
event.msg,
time: DateTime.fromMillisecondsSinceEpoch(event.timeMillis),
);
});
}
}
}

void initLocale() {
final localeMode = ConfigStore().localeMode();

if (localeMode == LocaleMode.system) {
LocaleSettings.useDeviceLocale();
} else {
final locale = ConfigStore().locale();
LocaleSettings.setLocaleRaw(stringToLocale(locale).languageCode);
}

if (Platform.isWindows) {
windowManager.setTitle(t.appTitle.parta + t.appTitle.partb);
}
}

extension MissionStateName on MissionState {
String getName() {
switch (this) {
case MissionState.idle:
// TODO: Handle this case.
case MissionState.pending:
return t.mission.pending;
case MissionState.transfering:
return t.mission.tranfer;
case MissionState.finished:
return t.mission.finished;
case MissionState.failed:
return t.mission.failed;
case MissionState.canceled:
return t.mission.cancel;
case MissionState.busy:
// TODO: Handle this case.
}
return "unknown";
}
}

extension FileStateName on FileState {
String getName() {
switch (this) {
case FileState_Pending():
return t.mission.pending;
case FileState_Transfer():
return t.mission.tranfer;
case FileState_Finish():
return t.mission.complete;
case FileState_Skip():
return t.mission.skip;
default:
return "unknown";
}
}
}
24 changes: 0 additions & 24 deletions lib/common/widgets.dart

This file was deleted.

4 changes: 4 additions & 0 deletions lib/core/providers/locale_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:window_manager/window_manager.dart';

import '../../common/constants.dart';
import '../../common/utils.dart';
Expand Down Expand Up @@ -46,6 +47,9 @@ class LocaleState extends _$LocaleState {
} else {
LocaleSettings.setLocaleRaw(state.customLocale.languageCode);
}
if (Platform.isWindows) {
windowManager.setTitle(t.appTitle.parta + t.appTitle.partb);
}
}

void setLocale(Locale locale) {
Expand Down
2 changes: 1 addition & 1 deletion lib/core/providers/locale_provider.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 34 additions & 2 deletions lib/core/rust/actor/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,37 @@
import '../frb_generated.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';

// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<CoreConfig>>
abstract class CoreConfig implements RustOpaqueInterface {}
class CoreConfig {
final int port;
final String interfaceAddr;
final String multicastAddr;
final int multicastPort;
final String storePath;

const CoreConfig({
required this.port,
required this.interfaceAddr,
required this.multicastAddr,
required this.multicastPort,
required this.storePath,
});

@override
int get hashCode =>
port.hashCode ^
interfaceAddr.hashCode ^
multicastAddr.hashCode ^
multicastPort.hashCode ^
storePath.hashCode;

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is CoreConfig &&
runtimeType == other.runtimeType &&
port == other.port &&
interfaceAddr == other.interfaceAddr &&
multicastAddr == other.multicastAddr &&
multicastPort == other.multicastPort &&
storePath == other.storePath;
}
10 changes: 6 additions & 4 deletions lib/core/rust/bridge.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
// These types are ignored because they are not used by any `pub` functions: `CORE`
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `deref`, `initialize`

Future<void> setup({required NodeDevice device}) =>
RustLib.instance.api.crateBridgeSetup(device: device);
Future<void> setup({required NodeDevice device, required CoreConfig config}) =>
RustLib.instance.api.crateBridgeSetup(device: device, config: config);

Stream<bool> listenServerState() =>
RustLib.instance.api.crateBridgeListenServerState();
Expand All @@ -26,8 +26,10 @@ Future<void> startServer() => RustLib.instance.api.crateBridgeStartServer();
Future<void> shutdownServer() =>
RustLib.instance.api.crateBridgeShutdownServer();

Future<void> changeAddress({required String addr}) =>
RustLib.instance.api.crateBridgeChangeAddress(addr: addr);
Future<void> restartServer() => RustLib.instance.api.crateBridgeRestartServer();

Future<void> changePath({required String path}) =>
RustLib.instance.api.crateBridgeChangePath(path: path);

Future<void> changeConfig({required CoreConfig config}) =>
RustLib.instance.api.crateBridgeChangeConfig(config: config);
Expand Down
Loading

0 comments on commit 4370689

Please sign in to comment.