Merge pull request #557 from venera-app/v1.5.3-dev

V1.5.3
This commit is contained in:
nyne
2025-10-13 20:42:31 +08:00
committed by GitHub
14 changed files with 312 additions and 312 deletions

View File

@@ -31,7 +31,7 @@ jobs:
- name: Update AltStore source - name: Update AltStore source
id: update_source id: update_source
env: env:
GITHUB_TOKEN: ${{ secrets.ACTION_GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
python update_alt_store.py python update_alt_store.py
git config --global user.name 'GitHub Action' git config --global user.name 'GitHub Action'
@@ -40,8 +40,19 @@ jobs:
if git diff --staged --quiet; then if git diff --staged --quiet; then
echo "changes=false" >> $GITHUB_OUTPUT echo "changes=false" >> $GITHUB_OUTPUT
else else
# Create a new branch for the PR
branch_name="update-altstore-$(date +%Y%m%d-%H%M%S)"
git checkout -b "$branch_name"
git commit -m "Updated source with latest release" git commit -m "Updated source with latest release"
git push git push -u origin "$branch_name"
# Create PR using GitHub CLI
gh pr create \
--title "Update AltStore source with latest release" \
--body "This PR updates the alt_store.json file with the latest release information." \
--head "$branch_name" \
--base main
echo "changes=true" >> $GITHUB_OUTPUT echo "changes=true" >> $GITHUB_OUTPUT
fi fi

View File

@@ -23,7 +23,7 @@ linter:
rules: rules:
collection_methods_unrelated_type: false collection_methods_unrelated_type: false
use_build_context_synchronously: false use_build_context_synchronously: false
# avoid_print: false # Uncomment to disable the `avoid_print` rule avoid_print: false
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at # Additional information about this file can be found at

View File

@@ -84,9 +84,8 @@ android {
buildTypes { buildTypes {
release { release {
// Temporarily solution to fix crash minifyEnabled true
minifyEnabled false shrinkResources true
shrinkResources false
ndk { ndk {
abiFilters "armeabi-v7a", "arm64-v8a", "x86_64" abiFilters "armeabi-v7a", "arm64-v8a", "x86_64"
} }

View File

@@ -13,7 +13,7 @@ export "widget_utils.dart";
export "context.dart"; export "context.dart";
class _App { class _App {
final version = "1.5.2"; final version = "1.5.3";
bool get isAndroid => Platform.isAndroid; bool get isAndroid => Platform.isAndroid;

View File

@@ -128,7 +128,7 @@ mixin _AppRouteTransitionMixin<T> on PageRoute<T> {
context, context,
animation, animation,
secondaryAnimation, secondaryAnimation,
enableIOSGesture enableIOSGesture && App.isIOS
? IOSBackGestureDetector( ? IOSBackGestureDetector(
gestureWidth: _kBackGestureWidth, gestureWidth: _kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(this), enabledCallback: () => _isPopGestureEnabled<T>(this),

View File

@@ -17,39 +17,50 @@ class CategoriesPage extends StatefulWidget {
State<CategoriesPage> createState() => _CategoriesPageState(); State<CategoriesPage> createState() => _CategoriesPageState();
} }
class _CategoriesPageState extends State<CategoriesPage> { class _CategoriesPageState extends State<CategoriesPage>
with
TickerProviderStateMixin,
AutomaticKeepAliveClientMixin<CategoriesPage> {
var categories = <String>[]; var categories = <String>[];
late TabController controller;
void onSettingsChanged() { void onSettingsChanged() {
var categories = var categories = List.from(
List.from(appdata.settings["categories"]).whereType<String>().toList(); appdata.settings["categories"],
).whereType<String>().toList();
var allCategories = ComicSource.all() var allCategories = ComicSource.all()
.map((e) => e.categoryData?.key) .map((e) => e.categoryData?.key)
.where((element) => element != null) .where((element) => element != null)
.map((e) => e!) .map((e) => e!)
.toList(); .toList();
categories = categories = categories
categories.where((element) => allCategories.contains(element)).toList(); .where((element) => allCategories.contains(element))
.toList();
if (!categories.isEqualTo(this.categories)) { if (!categories.isEqualTo(this.categories)) {
setState(() { setState(() {
this.categories = categories; this.categories = categories;
}); });
controller = TabController(length: categories.length, vsync: this);
} }
} }
@override @override
void initState() { void initState() {
super.initState(); super.initState();
var categories = var categories = List.from(
List.from(appdata.settings["categories"]).whereType<String>().toList(); appdata.settings["categories"],
).whereType<String>().toList();
var allCategories = ComicSource.all() var allCategories = ComicSource.all()
.map((e) => e.categoryData?.key) .map((e) => e.categoryData?.key)
.where((element) => element != null) .where((element) => element != null)
.map((e) => e!) .map((e) => e!)
.toList(); .toList();
this.categories = this.categories = categories
categories.where((element) => allCategories.contains(element)).toList(); .where((element) => allCategories.contains(element))
.toList();
appdata.settings.addListener(onSettingsChanged); appdata.settings.addListener(onSettingsChanged);
controller = TabController(length: categories.length, vsync: this);
} }
void addPage() { void addPage() {
@@ -59,6 +70,7 @@ class _CategoriesPageState extends State<CategoriesPage> {
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
controller.dispose();
appdata.settings.removeListener(onSettingsChanged); appdata.settings.removeListener(onSettingsChanged);
} }
@@ -85,17 +97,16 @@ class _CategoriesPageState extends State<CategoriesPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
if (categories.isEmpty) { if (categories.isEmpty) {
return buildEmpty(); return buildEmpty();
} }
return Material( return Material(
child: DefaultTabController(
length: categories.length,
key: Key(categories.toString()),
child: Column( child: Column(
children: [ children: [
AppTabBar( AppTabBar(
controller: controller,
key: PageStorageKey(categories.toString()), key: PageStorageKey(categories.toString()),
tabs: categories.map((e) { tabs: categories.map((e) {
String title = e; String title = e;
@@ -104,10 +115,7 @@ class _CategoriesPageState extends State<CategoriesPage> {
} catch (e) { } catch (e) {
// //
} }
return Tab( return Tab(text: title, key: Key(e));
text: title,
key: Key(e),
);
}).toList(), }).toList(),
actionButton: TabActionButton( actionButton: TabActionButton(
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
@@ -117,14 +125,17 @@ class _CategoriesPageState extends State<CategoriesPage> {
).paddingTop(context.padding.top), ).paddingTop(context.padding.top),
Expanded( Expanded(
child: TabBarView( child: TabBarView(
controller: controller,
children: categories.map((e) => _CategoryPage(e)).toList(), children: categories.map((e) => _CategoryPage(e)).toList(),
), ),
)
],
), ),
],
), ),
); );
} }
@override
bool get wantKeepAlive => true;
} }
typedef ClickTagCallback = void Function(String, String?); typedef ClickTagCallback = void Function(String, String?);
@@ -150,7 +161,8 @@ class _CategoryPage extends StatelessWidget {
var children = <Widget>[]; var children = <Widget>[];
if (data.enableRankingPage || data.buttons.isNotEmpty) { if (data.enableRankingPage || data.buttons.isNotEmpty) {
children.add(buildTitle(data.title)); children.add(buildTitle(data.title));
children.add(Padding( children.add(
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 16), padding: const EdgeInsets.fromLTRB(10, 0, 10, 16),
child: Wrap( child: Wrap(
children: [ children: [
@@ -159,29 +171,32 @@ class _CategoryPage extends StatelessWidget {
context.to(() => RankingPage(categoryKey: data.key)); context.to(() => RankingPage(categoryKey: data.key));
}), }),
for (var buttonData in data.buttons) for (var buttonData in data.buttons)
buildTag(buttonData.label.tl, buttonData.onTap) buildTag(buttonData.label.tl, buttonData.onTap),
], ],
), ),
)); ),
);
} }
for (var part in data.categories) { for (var part in data.categories) {
if (part.enableRandom) { if (part.enableRandom) {
children.add(StatefulBuilder(builder: (context, updater) { children.add(
StatefulBuilder(
builder: (context, updater) {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
buildTitleWithRefresh(part.title, () => updater(() {})), buildTitleWithRefresh(part.title, () => updater(() {})),
buildTags(part.categories) buildTags(part.categories),
], ],
); );
})); },
),
);
} else { } else {
children.add(buildTitle(part.title)); children.add(buildTitle(part.title));
children.add( children.add(buildTags(part.categories));
buildTags(part.categories),
);
} }
} }
return SingleChildScrollView( return SingleChildScrollView(
@@ -195,8 +210,10 @@ class _CategoryPage extends StatelessWidget {
Widget buildTitle(String title) { Widget buildTitle(String title) {
return Padding( return Padding(
padding: const EdgeInsets.fromLTRB(16, 10, 5, 10), padding: const EdgeInsets.fromLTRB(16, 10, 5, 10),
child: Text(title.tl, child: Text(
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500)), title.tl,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
); );
} }
@@ -207,21 +224,16 @@ class _CategoryPage extends StatelessWidget {
children: [ children: [
Text( Text(
title.tl, title.tl,
style: const TextStyle( style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
fontSize: 20,
fontWeight: FontWeight.w500,
),
), ),
const Spacer(), const Spacer(),
IconButton(onPressed: onRefresh, icon: const Icon(Icons.refresh)) IconButton(onPressed: onRefresh, icon: const Icon(Icons.refresh)),
], ],
), ),
); );
} }
Widget buildTags( Widget buildTags(List<CategoryItem> categories) {
List<CategoryItem> categories,
) {
return Padding( return Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 16), padding: const EdgeInsets.fromLTRB(10, 0, 10, 16),
child: Wrap( child: Wrap(

View File

@@ -155,18 +155,19 @@ abstract mixin class _ComicPageActions {
builder: (context, setState) { builder: (context, setState) {
return ContentDialog( return ContentDialog(
title: "Download".tl, title: "Download".tl,
content: Column( content: RadioGroup<int>(
groupValue: selected,
onChanged: (v) {
setState(() {
selected = v ?? selected;
});
},
child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
RadioListTile<int>( RadioListTile<int>(
value: -1, value: -1,
groupValue: selected,
title: Text("Normal".tl), title: Text("Normal".tl),
onChanged: (v) {
setState(() {
selected = v!;
});
},
), ),
ExpansionTile( ExpansionTile(
title: Text("Archive".tl), title: Text("Archive".tl),
@@ -201,12 +202,6 @@ abstract mixin class _ComicPageActions {
for (int i = 0; i < archives!.length; i++) for (int i = 0; i < archives!.length; i++)
RadioListTile<int>( RadioListTile<int>(
value: i, value: i,
groupValue: selected,
onChanged: (v) {
setState(() {
selected = v!;
});
},
title: Text(archives![i].title), title: Text(archives![i].title),
subtitle: Text(archives![i].description), subtitle: Text(archives![i].description),
) )
@@ -214,6 +209,7 @@ abstract mixin class _ComicPageActions {
) )
], ],
), ),
),
actions: [ actions: [
Button.filled( Button.filled(
isLoading: isGettingLink, isLoading: isGettingLink,
@@ -237,10 +233,12 @@ abstract mixin class _ComicPageActions {
isGettingLink = false; isGettingLink = false;
}); });
} else if (context.mounted) { } else if (context.mounted) {
if (res.data.isNotEmpty) {
LocalManager() LocalManager()
.addTask(ArchiveDownloadTask(res.data, comic)); .addTask(ArchiveDownloadTask(res.data, comic));
App.rootContext App.rootContext
.showMessage(message: "Download started".tl); .showMessage(message: "Download started".tl);
}
context.pop(); context.pop();
} }
}, },

View File

@@ -514,21 +514,22 @@ class _ImportComicsWidgetState extends State<_ImportComicsWidget> {
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
), ),
) )
: Column( : RadioGroup<int>(
groupValue: type,
onChanged: (value) {
setState(() {
type = value ?? type;
});
},
child: Column(
key: key, key: key,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(width: 600), const SizedBox(width: 600),
...List.generate(importMethods.length, (index) { ...List.generate(importMethods.length, (index) {
return RadioListTile( return RadioListTile<int>(
title: Text(importMethods[index]), title: Text(importMethods[index]),
value: index, value: index,
groupValue: type,
onChanged: (value) {
setState(() {
type = value as int;
});
},
); );
}), }),
if (type != 4) if (type != 4)
@@ -559,6 +560,7 @@ class _ImportComicsWidgetState extends State<_ImportComicsWidget> {
Text(info).paddingHorizontal(24), Text(info).paddingHorizontal(24),
], ],
), ),
),
actions: [ actions: [
Button.text( Button.text(
child: Row( child: Row(

View File

@@ -404,22 +404,24 @@ class _ImageFavoritesDialogState extends State<_ImageFavoritesDialog> {
children: [ children: [
tabBar, tabBar,
TabViewBody(children: [ TabViewBody(children: [
Column( RadioGroup<ImageFavoriteSortType>(
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v ?? sortType;
});
},
child: Column(
children: ImageFavoriteSortType.values children: ImageFavoriteSortType.values
.map( .map(
(e) => RadioListTile<ImageFavoriteSortType>( (e) => RadioListTile<ImageFavoriteSortType>(
title: Text(e.value.tl), title: Text(e.value.tl),
value: e, value: e,
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v!;
});
},
), ),
) )
.toList(), .toList(),
), ),
),
Column( Column(
children: [ children: [
ListTile( ListTile(

View File

@@ -70,40 +70,30 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
return StatefulBuilder(builder: (context, setState) { return StatefulBuilder(builder: (context, setState) {
return ContentDialog( return ContentDialog(
title: "Sort".tl, title: "Sort".tl,
content: Column( content: RadioGroup<LocalSortType>(
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v ?? sortType;
});
},
child: Column(
children: [ children: [
RadioListTile<LocalSortType>( RadioListTile<LocalSortType>(
title: Text("Name".tl), title: Text("Name".tl),
value: LocalSortType.name, value: LocalSortType.name,
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v!;
});
},
), ),
RadioListTile<LocalSortType>( RadioListTile<LocalSortType>(
title: Text("Date".tl), title: Text("Date".tl),
value: LocalSortType.timeAsc, value: LocalSortType.timeAsc,
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v!;
});
},
), ),
RadioListTile<LocalSortType>( RadioListTile<LocalSortType>(
title: Text("Date Desc".tl), title: Text("Date Desc".tl),
value: LocalSortType.timeDesc, value: LocalSortType.timeDesc,
groupValue: sortType,
onChanged: (v) {
setState(() {
sortType = v!;
});
},
), ),
], ],
), ),
),
actions: [ actions: [
FilledButton( FilledButton(
onPressed: () { onPressed: () {

View File

@@ -428,31 +428,27 @@ class _WebdavSettingState extends State<_WebdavSetting> {
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
Row( RadioGroup<bool>(
groupValue: upload,
onChanged: (value) {
setState(() {
upload = value ?? upload;
});
},
child: Row(
children: [ children: [
Text("Operation".tl), Text("Operation".tl),
Radio<bool>( Radio<bool>(
groupValue: upload,
value: true, value: true,
onChanged: (value) {
setState(() {
upload = value!;
});
},
), ),
Text("Upload".tl), Text("Upload".tl),
Radio<bool>( Radio<bool>(
groupValue: upload,
value: false, value: false,
onChanged: (value) {
setState(() {
upload = value!;
});
},
), ),
Text("Download".tl), Text("Download".tl),
], ],
), ),
),
const SizedBox(height: 16), const SizedBox(height: 16),
AnimatedSize( AnimatedSize(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),

View File

@@ -111,46 +111,36 @@ class _ProxySettingViewState extends State<_ProxySettingView> {
return PopUpWidgetScaffold( return PopUpWidgetScaffold(
title: "Proxy".tl, title: "Proxy".tl,
body: SingleChildScrollView( body: SingleChildScrollView(
child: RadioGroup<String>(
groupValue: type,
onChanged: (v) {
setState(() {
type = v ?? type;
});
if (type != 'manual') {
appdata.settings['proxy'] = toProxyStr();
appdata.saveData();
}
},
child: Column( child: Column(
children: [ children: [
RadioListTile<String>( RadioListTile<String>(
title: Text("Direct".tl), title: Text("Direct".tl),
value: 'direct', value: 'direct',
groupValue: type,
onChanged: (v) {
setState(() {
type = v!;
});
appdata.settings['proxy'] = toProxyStr();
appdata.saveData();
},
), ),
RadioListTile<String>( RadioListTile<String>(
title: Text("System".tl), title: Text("System".tl),
value: 'system', value: 'system',
groupValue: type,
onChanged: (v) {
setState(() {
type = v!;
});
appdata.settings['proxy'] = toProxyStr();
appdata.saveData();
},
), ),
RadioListTile( RadioListTile(
title: Text("Manual".tl), title: Text("Manual".tl),
value: 'manual', value: 'manual',
groupValue: type,
onChanged: (v) {
setState(() {
type = v!;
});
},
), ),
if (type == 'manual') buildManualProxy(), if (type == 'manual') buildManualProxy(),
], ],
), ),
), ),
),
); );
} }

View File

@@ -416,10 +416,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_memory_info name: flutter_memory_info
sha256: "1f112f1d7503aa1681fc8e923f6cd0e847bb2fbeec3753ed021cf1e5f7e9cd74" sha256: eacfd0dd01ff596b4e5bf022442769a1807a73f2af43d62802436f0a5de99137
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.0.1" version: "0.0.3"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:

View File

@@ -2,7 +2,7 @@ name: venera
description: "A comic app." description: "A comic app."
publish_to: 'none' publish_to: 'none'
version: 1.5.2+152 version: 1.5.3+153
environment: environment:
sdk: '>=3.8.0 <4.0.0' sdk: '>=3.8.0 <4.0.0'
@@ -75,7 +75,7 @@ dependencies:
ref: fe182cdf40e5fa6230f451bc1d643b860f610d13 ref: fe182cdf40e5fa6230f451bc1d643b860f610d13
dynamic_color: ^1.7.0 dynamic_color: ^1.7.0
shimmer_animation: ^2.1.0 shimmer_animation: ^2.1.0
flutter_memory_info: ^0.0.1 flutter_memory_info: ^0.0.3
syntax_highlight: ^0.4.0 syntax_highlight: ^0.4.0
flutter_7zip: flutter_7zip:
git: git: