Skip to content

Commit

Permalink
Merge pull request #5 from guchengxi1994/dev
Browse files Browse the repository at this point in the history
v0.1.5
  • Loading branch information
guchengxi1994 committed Apr 18, 2023
2 parents 8201344 + 27dbe11 commit 8d6c01a
Show file tree
Hide file tree
Showing 46 changed files with 1,307 additions and 186 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

## changelogs

* **0.1.5** add some features

* 0.1.5+3 keyboard onKeyDown/up preview

![image-20230418175235424](./screenshots/image-20230418175235424.png)

* 0.1.5+2 notifications (WIP)

![image-20230418153645695](./screenshots/image-20230418153645695.png)

* 0.1.5+1 custom volume controller (WIP)

![image-20230418111207573](./screenshots/image-20230418111207573.png)

* **0.1.4**

* **0.1.4+3** highlight taskbar app icons && context menu
Expand All @@ -14,7 +28,7 @@

![image-20230415123427502](./screenshots/image-20230415123427502.png)

* **0.1.3** add logger (native)
* **0.1.3** add logger (rust backend)

* **0.1.2** taskbar & status-bar

Expand Down
Binary file added assets/images/appicons/audio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/appicons/player.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/appicons/unknow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions lib/bridge/bridge_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ abstract class Native {
Future<void> newLog({required String content, String? result, dynamic hint});

FlutterRustBridgeTaskConstMeta get kNewLogConstMeta;

/// files
Future<int> newFile(
{required String virtualPath, required String realPath, dynamic hint});

FlutterRustBridgeTaskConstMeta get kNewFileConstMeta;
}

class NativeImpl implements Native {
Expand Down Expand Up @@ -105,6 +111,25 @@ class NativeImpl implements Native {
argNames: ["content", "result"],
);

Future<int> newFile(
{required String virtualPath, required String realPath, dynamic hint}) {
var arg0 = _platform.api2wire_String(virtualPath);
var arg1 = _platform.api2wire_String(realPath);
return _platform.executeNormal(FlutterRustBridgeTask(
callFfi: (port_) => _platform.inner.wire_new_file(port_, arg0, arg1),
parseSuccessData: _wire2api_i64,
constMeta: kNewFileConstMeta,
argValues: [virtualPath, realPath],
hint: hint,
));
}

FlutterRustBridgeTaskConstMeta get kNewFileConstMeta =>
const FlutterRustBridgeTaskConstMeta(
debugName: "new_file",
argNames: ["virtualPath", "realPath"],
);

void dispose() {
_platform.dispose();
}
Expand All @@ -114,6 +139,10 @@ class NativeImpl implements Native {
return raw as String;
}

int _wire2api_i64(dynamic raw) {
return castInt(raw);
}

int _wire2api_u8(dynamic raw) {
return raw as int;
}
Expand Down Expand Up @@ -320,6 +349,26 @@ class NativeWire implements FlutterRustBridgeWireBase {
void Function(
int, ffi.Pointer<wire_uint_8_list>, ffi.Pointer<wire_uint_8_list>)>();

void wire_new_file(
int port_,
ffi.Pointer<wire_uint_8_list> virtual_path,
ffi.Pointer<wire_uint_8_list> real_path,
) {
return _wire_new_file(
port_,
virtual_path,
real_path,
);
}

late final _wire_new_filePtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(ffi.Int64, ffi.Pointer<wire_uint_8_list>,
ffi.Pointer<wire_uint_8_list>)>>('wire_new_file');
late final _wire_new_file = _wire_new_filePtr.asFunction<
void Function(
int, ffi.Pointer<wire_uint_8_list>, ffi.Pointer<wire_uint_8_list>)>();

ffi.Pointer<wire_uint_8_list> new_uint_8_list_0(
int len,
) {
Expand Down
1 change: 1 addition & 0 deletions lib/components/app_style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ class SystemConfig {
static const String sMyComputer = "我的电脑";
static const String sRecycle = "回收站";
static const String sAppManagement = "管理";
static const String sAudioPlayer = "音乐播放器";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
// ignore_for_file: use_build_context_synchronously, prefer_typing_uninitialized_variables

import 'dart:async';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_desktop/components/app_style.dart';
import 'package:flutter_desktop/components/applications/_system_applications/widgets/volume_slider.dart';
import 'package:flutter_desktop/components/notifications/notification_controller.dart';
import 'package:flutter_desktop/components/notifications/notification_details.dart';
import 'package:provider/provider.dart';
import 'package:siri_wave/siri_wave.dart';

import '../../utils.dart' show durationToMinuts;
import '../application.dart';
import 'details.dart';

Application audioPlayerApplication({String? audioPath}) {
return Application(
resizable: audioPlayerDetails.resizable,
uuid: audioPlayerDetails.uuid,
name: audioPlayerDetails.name,
child: AudioPlayerForm(
audioPath: audioPath,
),
);
}

class AudioPlayerController {
static final player = AudioPlayer();

static stop() async {
await player.stop();
}

static pause() async {
await player.pause();
}

static resume() async {
await player.resume();
}

static setPath(String s) async {
await player.setSource(DeviceFileSource(s));
}

static setVolume(double v) async {
assert(v >= 0 && v <= 1);
await player.setVolume(v);
}

static setDuration(Duration d) async {
await player.seek(d);
}

static getDuration() async {
return await player.getDuration();
}
}

class AudioPlayerForm extends StatefulWidget {
const AudioPlayerForm({super.key, required this.audioPath});
final String? audioPath;

@override
State<AudioPlayerForm> createState() => _AudioPlayerFormState();
}

class _AudioPlayerFormState extends State<AudioPlayerForm> {
bool isPlaying = false;
late final lisener;
late final lisener2;
final _controller = SiriWaveController();
final scrollerController = ScrollController();
late final Timer timer;
late int _count = 0;
static const double length = 1000;
static const int frequency = 5;
static const double gap = 10;
late Duration duration = Duration.zero;
late Duration currentDuration = Duration.zero;
final GlobalKey<State<Slider>> sliderKey = GlobalKey();
double f = 0;
double volumn = 0.15;
late String? audioPath = widget.audioPath ?? /* for test */
r"D:\CloudMusic\CANT太子 - 类少年爱情故事(钢琴版).mp3";

@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
/// TODO
///
/// remove !
volumn = 0.15;
await AudioPlayerController.setPath(audioPath!);
await AudioPlayerController.setVolume(volumn);
await Future.delayed(const Duration(milliseconds: 1000))
.then((value) async {
duration = await AudioPlayerController.getDuration()!;
setState(() {});
});
});

lisener = AudioPlayerController.player.onPositionChanged.listen((event) {
setState(() {
currentDuration = event;
// print(currentDuration.inSeconds);
if (duration.inSeconds != 0) {
f = currentDuration.inSeconds / duration.inSeconds;
}
});
});

lisener2 = AudioPlayerController.player.onPlayerComplete.listen((event) {
setState(() {
isPlaying = false;
});
});

timer = Timer.periodic(const Duration(milliseconds: 200), (timer) {
_count += 1;
if ((_count * frequency) > length - 50) {
_count = 0;
}
scrollerController.jumpTo(_count * gap);
});
}

@override
void dispose() {
lisener.cancel();
lisener2.cancel();
timer.cancel();
super.dispose();
}

Widget _scrollableText(String s) {
return SizedBox(
width: 200,
child: SingleChildScrollView(
controller: scrollerController,
scrollDirection: Axis.horizontal,
child: Container(
padding: const EdgeInsets.only(left: 100),
width: length,
child: Text(
s,
maxLines: 1,
style: const TextStyle(color: AppStyle.light2),
),
),
),
);
}

@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: AppStyle.dark, borderRadius: BorderRadius.circular(5)),
width: 200,
height: 200,
padding: const EdgeInsets.all(15),
child: Column(children: [
_scrollableText(audioPath ?? "未找到音乐文件"),
isPlaying
? Expanded(
child: SiriWave(
controller: _controller,
),
)
: const Expanded(
child: SizedBox(),
),
]),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(durationToMinuts(currentDuration)),
Slider(
key: sliderKey,
value: f,
onChanged: (v) {
setState(() {
currentDuration =
Duration(seconds: (duration.inSeconds * v).ceil());
AudioPlayerController.setDuration(currentDuration);
});
}),
Text(durationToMinuts(duration)),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {}, child: const Icon(Icons.skip_previous)),
ElevatedButton(
onPressed: () {
if (audioPath == null) {
return;
}
setState(() {
isPlaying = !isPlaying;
});
if (isPlaying) {
AudioPlayerController.resume();
} else {
AudioPlayerController.pause();
}
},
child: isPlaying
? const Icon(Icons.pause)
: const Icon(Icons.play_arrow)),
ElevatedButton(
onPressed: () {
/// TODO
///
/// remove this
context.read<NotificationController>().raiseANotification(
NotificationDetails(
subject: DateTime.now().toString(),
uuid: audioPlayerDetails.uuid,
name: audioPlayerDetails.name,
icon: audioPlayerDetails.icon,
content: const Text("下一个")));
},
child: const Icon(Icons.skip_next)),
],
),
const SizedBox(
height: 20,
),
Row(
children: [
const Expanded(child: SizedBox()),
RepaintBoundary(
child: CustomVolumeSliderWidget(
width: 75,
height: 30,
onSliderChanged: (p0) async {
setState(() {
volumn = p0;
});
await AudioPlayerController.setVolume(volumn);
}),
),
const SizedBox(
width: 40,
)
],
)
],
);
}
}
11 changes: 11 additions & 0 deletions lib/components/applications/_system_applications/details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,14 @@ ApplicationDetails appManagementDetails = ApplicationDetails(
needsTrayDisplay: true,
iconUrl: "assets/images/appicons/management.png",
deletable: false);

ApplicationDetails audioPlayerDetails = ApplicationDetails(
uuid: const Uuid().v1(),
xmax: 300,
ymax: 400,
name: SystemConfig.sAudioPlayer,
needsTaskbarDisplay: true,
needsTrayDisplay: true,
iconUrl: "assets/images/appicons/player.png",
deletable: false,
resizable: false);
Loading

0 comments on commit 8d6c01a

Please sign in to comment.