Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions android/app/src/main/java/com/example/piliplus/AndroidHelper.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.piliplus;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
Expand All @@ -15,6 +16,7 @@
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Icon;
import android.media.session.PlaybackState;
import android.net.Uri;
Expand All @@ -31,7 +33,10 @@

import com.github.dart_lang.jni_flutter.JniFlutterPlugin;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;

@Keep
Expand Down Expand Up @@ -261,6 +266,27 @@ public static void createShortcut(@NonNull String id, @NonNull String uri, @NonN
}
}

@SuppressLint("BlockedPrivateApi")
public static String[] fontFamilies() {
Map<String, Typeface> systemFontMap = null;
try {
Method method = Typeface.class.getDeclaredMethod("getSystemFontMap");
method.setAccessible(true);
systemFontMap = (Map<String, Typeface>) method.invoke(null);
} catch (Exception ignored) {
try {
@SuppressLint("DiscouragedPrivateApi") Field field = Typeface.class.getDeclaredField("sSystemFontMap");
field.setAccessible(true);
systemFontMap = (Map<String, Typeface>) field.get(null);
} catch (Exception ignored0) {
}
}
if (null != systemFontMap) {
return systemFontMap.keySet().toArray(new String[0]);
}
return null;
}

@Keep
public static final class ToDart {
public static volatile Runnable onUserLeaveHint;
Expand Down
10 changes: 7 additions & 3 deletions lib/pages/dynamics/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
import 'package:PiliPlus/utils/extension/string_ext.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:easy_debounce/easy_throttle.dart';
import 'package:material_ui/material_ui.dart';
import 'package:get/get.dart';
import 'package:material_ui/material_ui.dart' show TabController;

class DynamicsController
extends CommonDataController<FollowUpModel, FollowUpModel>
Expand Down Expand Up @@ -98,8 +98,12 @@ class DynamicsController

@override
Future<void> onRefresh() {
singleRefresh();
return controller!.onRefresh();
final controller = this.controller;
if (controller != null) {
singleRefresh();
return controller.onRefresh();
}
return singleRefresh();
}

@override
Expand Down
14 changes: 13 additions & 1 deletion lib/pages/main/controller.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'dart:async';
import 'dart:math' as math;

import 'package:PiliPlus/grpc/dyn.dart';
import 'package:PiliPlus/harmony_adapt/harmony_channel.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/msg.dart';
import 'package:PiliPlus/models/common/dynamic/dynamic_badge_mode.dart';
import 'package:PiliPlus/models/common/home_tab_type.dart';
import 'package:PiliPlus/models/common/msg/msg_unread_type.dart';
import 'package:PiliPlus/models/common/nav_bar_config.dart';
import 'package:PiliPlus/pages/dynamics/controller.dart';
Expand Down Expand Up @@ -350,7 +352,7 @@ class MainController extends GetxController
}
this.navigationBars = navigationBars;
final defPage = Pref.defaultHomePage;
selectedIndex.value = navigationBars.indexOf(defPage);
selectedIndex.value = math.max(0, navigationBars.indexOf(defPage));
}

void checkDefaultSearch([bool shouldCheck = false]) {
Expand Down Expand Up @@ -451,6 +453,16 @@ class MainController extends GetxController
}
}

bool refreshRecommendations() {
if (navigationBars[selectedIndex.value] == NavigationBarType.home &&
homeController.tabs[homeController.tabController.index] ==
HomeTabType.rcmd) {
homeController.onRefresh();
return true;
}
return false;
}

@override
void onClose() {
if (OS.isHarmony) {
Expand Down
55 changes: 42 additions & 13 deletions lib/pages/main/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class _MainAppState extends PopScopeState<MainApp>
);
_syncPrimaryColor();
});
if (Platform.isMacOS) {
HardwareKeyboard.instance.addHandler(_handleKeyEvent);
}
if (PlatformUtils.isDesktop) {
windowManager
..addListener(this)
Expand Down Expand Up @@ -170,6 +173,9 @@ class _MainAppState extends PopScopeState<MainApp>
void dispose() {
_nativeTabsWorker?.dispose();
_nativeTopBarWorker?.dispose();
if (Platform.isMacOS) {
HardwareKeyboard.instance.removeHandler(_handleKeyEvent);
}
if (PlatformUtils.isDesktop) {
trayManager.removeListener(this);
windowManager.removeListener(this);
Expand All @@ -180,6 +186,13 @@ class _MainAppState extends PopScopeState<MainApp>
super.dispose();
}

bool _handleKeyEvent(KeyEvent event) {
return event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.keyR &&
HardwareKeyboard.instance.isMetaPressed &&
_mainController.refreshRecommendations();
}

@override
void onWindowMaximize() {
_setting.put(SettingBoxKey.isWindowMaximized, true);
Expand Down Expand Up @@ -347,19 +360,35 @@ class _MainAppState extends PopScopeState<MainApp>
return null;
}
if (_mainController.floatingNavBar) {
bottomNav = Obx(
() => FloatingNavigationBar(
onDestinationSelected: _mainController.setIndex,
selectedIndex: _mainController.selectedIndex.value,
destinations: _mainController.navigationBars
.map(
(e) => FloatingNavigationDestination(
label: e.label,
icon: _buildIcon(type: e),
selectedIcon: _buildIcon(type: e, selected: true),
),
)
.toList(),
// 悬浮底栏必须拿到「松」的宽度约束才能保持自身 destinations.length * 86 的
// 宽度。上游从 `e89241109 opt ui` 起把主页换成了自绘的 MainLayout,那里给
// bottomNav 的是 constraints.loosen() 再手动水平居中;鸿蒙没跟进这个骨架
// 重构(状态栏取色依赖 Scaffold 里那个零高 AppBar,换掉代价太大),而
// Scaffold.bottomNavigationBar 下发的是 fullWidthConstraints —— 宽度是紧
// 约束(material/scaffold.dart:1035 `looseConstraints.tighten(width:)`),
// FloatingNavigationBar 内部的 SizedBox 会被 enforce 成整屏宽。
//
// 这里用 Align 吃掉紧宽度:Align 自己撑满宽度,子节点拿到松约束、按自身
// 宽度水平居中;heightFactor: 1 让高度仍按子节点算,Scaffold 据此计算的
// body 内边距与改动前一致。两侧空白区域 Align 不参与命中测试,点击会穿透
// 到下面的内容,与上游 MainLayout 的表现一致。
bottomNav = Align(
alignment: Alignment.bottomCenter,
heightFactor: 1,
child: Obx(
() => FloatingNavigationBar(
onDestinationSelected: _mainController.setIndex,
selectedIndex: _mainController.selectedIndex.value,
destinations: _mainController.navigationBars
.map(
(e) => FloatingNavigationDestination(
label: e.label,
icon: _buildIcon(type: e),
selectedIcon: _buildIcon(type: e, selected: true),
),
)
.toList(),
),
),
);
} else if (_mainController.enableMYBar) {
Expand Down
24 changes: 24 additions & 0 deletions lib/pages/setting/models/extra_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,12 @@ List<SettingsModel> get extraSettings => [
getSubtitle: () => '当前优先展示「${Pref.replySortType.title}」',
onTap: _showReplySortDialog,
),
NormalModel(
title: '二级评论展示',
leading: const Icon(Icons.subdirectory_arrow_right_outlined),
getSubtitle: () => '当前优先展示「${Pref.reply2SortType.title}」',
onTap: _showReply2SortDialog,
),
NormalModel(
title: '动态展示',
leading: const Icon(Icons.dynamic_feed_rounded),
Expand Down Expand Up @@ -1103,6 +1109,24 @@ Future<void> _showReplySortDialog(
}
}

Future<void> _showReply2SortDialog(
BuildContext context,
VoidCallback setState,
) async {
final res = await showDialog<ReplySortType>(
context: context,
builder: (context) => SelectDialog<ReplySortType>(
title: '二级评论展示',
value: Pref.reply2SortType,
values: ReplySortType.values.take(2).map((e) => (e, e.title)).toList(),
),
);
if (res != null) {
await GStorage.setting.put(SettingBoxKey.reply2SortType, res.index);
setState();
}
}

Future<void> _showDefDynDialog(
BuildContext context,
VoidCallback setState,
Expand Down
48 changes: 5 additions & 43 deletions lib/pages/setting/models/style_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,11 @@ List<SettingsModel> get styleSettings => [
defaultVal: false,
needReboot: true,
),
SplitModel(
normalModel: const NormalModel.split(
title: 'App字体字重',
subtitle: '点击设置',
leading: Icon(Icons.text_fields),
),
switchModel: SwitchModel.split(
defaultVal: false,
setKey: SettingBoxKey.appFontWeight,
onChanged: (_) => Get.updateMyAppTheme(),
onTap: _showFontWeightDialog,
),
NormalModel(
title: 'App字体设置',
subtitle: '点击设置',
leading: const Icon(Icons.text_fields),
onTap: (context, setState) => Get.toNamed('/fontSetting'),
),
NormalModel(
title: '界面缩放',
Expand Down Expand Up @@ -329,20 +322,6 @@ List<SettingsModel> get styleSettings => [
leading: Icon(Icons.chrome_reader_mode_outlined),
onTap: _showSpringDialog,
),
NormalModel(
onTap: (context, setState) async {
final res = await Get.toNamed('/fontSizeSetting');
if (res != null) {
setState();
}
},
title: '字体大小',
leading: const Icon(Icons.format_size_outlined),
getSubtitle: () {
final scale = Pref.defaultTextScale;
return scale == 1.0 ? '默认' : scale.toString();
},
),
NormalModel(
onTap: (context, setState) => Get.toNamed(
'/barSetting',
Expand Down Expand Up @@ -637,23 +616,6 @@ void _showSpringDialog(BuildContext context, _) {
);
}

Future<void> _showFontWeightDialog(BuildContext context) async {
final res = await showDialog<double>(
context: context,
builder: (context) => SliderDialog(
title: const Text('App字体字重'),
value: Pref.appFontWeight.toDouble() + 1,
min: 1,
max: FontWeight.values.length.toDouble(),
divisions: FontWeight.values.length - 1,
),
);
if (res != null) {
await GStorage.setting.put(SettingBoxKey.appFontWeight, res.toInt() - 1);
Get.updateMyAppTheme();
}
}

Future<void> _showTransitionDialog(
BuildContext context,
VoidCallback setState,
Expand Down
28 changes: 28 additions & 0 deletions lib/pages/setting/models/video_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ List<SettingsModel> get videoSettings => [
'首选解码格式:${(Pref.preferCodecs.map((i) => i.name).join(","))},请根据设备支持情况与需求调整',
onTap: _showCodecsDialog,
),
NormalModel(
title: '蜂窝网络首选解码格式',
leading: const Icon(Icons.movie_creation_outlined),
getSubtitle: () =>
'首选解码格式:${(Pref.preferCodecsCellular.map((i) => i.name).join(","))},请根据设备支持情况与需求调整',
onTap: _showCellularCodecsDialog,
),
if (kDebugMode || Platform.isAndroid)
NormalModel(
title: '音频输出设备',
Expand Down Expand Up @@ -363,6 +370,27 @@ Future<void> _showCodecsDialog(
}
}

Future<void> _showCellularCodecsDialog(
BuildContext context,
VoidCallback setState,
) async {
final res = await showDialog<List<VideoDecodeFormatType>>(
context: context,
builder: (context) => OrderedMultiSelectDialog<VideoDecodeFormatType>(
title: '蜂窝网络首选解码格式',
initValues: Pref.preferCodecsCellular,
values: {for (final e in VideoDecodeFormatType.values) e: e.name},
),
);
if (res != null && res.isNotEmpty) {
await GStorage.setting.put(
SettingBoxKey.preferCodecsCellular,
res.map((i) => i.name).toList(),
);
setState();
}
}

Future<void> _showAudioOutputDialog(
BuildContext context,
VoidCallback setState,
Expand Down
Loading
Loading