mirror of
https://github.com/wgh136/pixes.git
synced 2025-09-27 04:57:23 +00:00
block tags and authors
This commit is contained in:
15
.vscode/settings.json
vendored
Normal file
15
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"appdata",
|
||||||
|
"Bungo",
|
||||||
|
"gjzr",
|
||||||
|
"microtask",
|
||||||
|
"mypixiv",
|
||||||
|
"pawoo",
|
||||||
|
"Rorigod",
|
||||||
|
"sleepinglife",
|
||||||
|
"Ugoira",
|
||||||
|
"vocaloidhm",
|
||||||
|
"vsync"
|
||||||
|
]
|
||||||
|
}
|
@@ -64,9 +64,9 @@
|
|||||||
"Weekly Manga": "每周漫画",
|
"Weekly Manga": "每周漫画",
|
||||||
"Monthly Manga": "每月漫画",
|
"Monthly Manga": "每月漫画",
|
||||||
"R18": "R18",
|
"R18": "R18",
|
||||||
"Account": "账户",
|
"Account": "账号",
|
||||||
"Logout": "登出",
|
"Logout": "登出",
|
||||||
"Account Settings": "账户设置",
|
"Account Settings": "账号设置",
|
||||||
"Edit": "编辑",
|
"Edit": "编辑",
|
||||||
"Download": "下载",
|
"Download": "下载",
|
||||||
"Manage": "管理",
|
"Manage": "管理",
|
||||||
@@ -138,7 +138,16 @@
|
|||||||
"Line Height": "行高",
|
"Line Height": "行高",
|
||||||
"Paragraph Spacing": "段间距",
|
"Paragraph Spacing": "段间距",
|
||||||
"light": "浅色",
|
"light": "浅色",
|
||||||
"dark": "深色"
|
"dark": "深色",
|
||||||
|
"block": "屏蔽",
|
||||||
|
"Block": "屏蔽",
|
||||||
|
"Block(Account)": "屏蔽(账号)",
|
||||||
|
"Block(Local)": "屏蔽(本地)",
|
||||||
|
"Add": "添加",
|
||||||
|
"Submit": "提交",
|
||||||
|
"Local": "本地",
|
||||||
|
"Both": "同时",
|
||||||
|
"This artwork is blocked": "此作品已被屏蔽"
|
||||||
},
|
},
|
||||||
"zh_TW": {
|
"zh_TW": {
|
||||||
"Search": "搜索",
|
"Search": "搜索",
|
||||||
@@ -279,6 +288,15 @@
|
|||||||
"Line Height": "行高",
|
"Line Height": "行高",
|
||||||
"Paragraph Spacing": "段間距",
|
"Paragraph Spacing": "段間距",
|
||||||
"light": "淺色",
|
"light": "淺色",
|
||||||
"dark": "深色"
|
"dark": "深色",
|
||||||
|
"block": "屏蔽",
|
||||||
|
"Block": "屏蔽",
|
||||||
|
"Block(Account)": "屏蔽(賬戶)",
|
||||||
|
"Block(Local)": "屏蔽(本地)",
|
||||||
|
"Add": "添加",
|
||||||
|
"Submit": "提交",
|
||||||
|
"Local": "本地",
|
||||||
|
"Both": "同時",
|
||||||
|
"This artwork is blocked": "此作品已被屏蔽"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -527,3 +527,25 @@ class Novel {
|
|||||||
commentsCount = json["total_comments"],
|
commentsCount = json["total_comments"],
|
||||||
isAi = json["novel_ai_type"] == 2;
|
isAi = json["novel_ai_type"] == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MuteList {
|
||||||
|
List<Tag> tags;
|
||||||
|
|
||||||
|
List<Author> authors;
|
||||||
|
|
||||||
|
int limit;
|
||||||
|
|
||||||
|
MuteList(this.tags, this.authors, this.limit);
|
||||||
|
|
||||||
|
static MuteList? fromJson(Map<String, dynamic> data) {
|
||||||
|
return MuteList(
|
||||||
|
(data['muted_tags'] as List)
|
||||||
|
.map((e) => Tag(e['tag'], e['tag_translation']))
|
||||||
|
.toList(),
|
||||||
|
(data['muted_users'] as List)
|
||||||
|
.map((e) => Author(e['user_id'], e['user_name'], e['user_account'],
|
||||||
|
e['user_profile_image_urls']['medium'], false))
|
||||||
|
.toList(),
|
||||||
|
data['mute_limit_count']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -191,6 +191,21 @@ class Network {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String? encodeFormData(Map<String, dynamic>? data) {
|
||||||
|
if (data == null) return null;
|
||||||
|
StringBuffer buffer = StringBuffer();
|
||||||
|
data.forEach((key, value) {
|
||||||
|
if (value is List) {
|
||||||
|
for (var element in value) {
|
||||||
|
buffer.write("$key[]=$element&");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.write("$key=$value&");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
Future<Res<Map<String, dynamic>>> apiPost(String path,
|
Future<Res<Map<String, dynamic>>> apiPost(String path,
|
||||||
{Map<String, dynamic>? query, Map<String, dynamic>? data}) async {
|
{Map<String, dynamic>? query, Map<String, dynamic>? data}) async {
|
||||||
try {
|
try {
|
||||||
@@ -199,7 +214,7 @@ class Network {
|
|||||||
}
|
}
|
||||||
final res = await dio.post<Map<String, dynamic>>(path,
|
final res = await dio.post<Map<String, dynamic>>(path,
|
||||||
queryParameters: query,
|
queryParameters: query,
|
||||||
data: data,
|
data: encodeFormData(data),
|
||||||
options: Options(
|
options: Options(
|
||||||
headers: headers,
|
headers: headers,
|
||||||
validateStatus: (status) => true,
|
validateStatus: (status) => true,
|
||||||
@@ -497,21 +512,24 @@ class Network {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Tag>> getMutedTags() async {
|
Future<Res<MuteList>> getMuteList() async {
|
||||||
var res = await apiGet("/v1/mute/list");
|
var res = await apiGet("/v1/mute/list");
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
return res.data["mute_tags"]
|
return Res(MuteList.fromJson(res.data));
|
||||||
.map<Tag>((e) => Tag(e["tag"]["name"], e["tag"]["translated_name"]))
|
|
||||||
.toList();
|
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return Res.error(res.errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Res<bool>> muteTags(
|
Future<Res<bool>> editMute(List<String> addTags, List<String> addUsers,
|
||||||
List<String> muteTags, List<String> unmuteTags) async {
|
List<String> deleteTags, List<String> deleteUsers) async {
|
||||||
var res = await apiPost("/v1/mute/edit",
|
var res = await apiPost("/v1/mute/edit",
|
||||||
data: {"add_tags": muteTags, "delete_tags": unmuteTags});
|
data: {
|
||||||
|
"add_tags": addTags,
|
||||||
|
"add_user_ids": addUsers,
|
||||||
|
"delete_tags": deleteTags,
|
||||||
|
"delete_user_ids": deleteUsers
|
||||||
|
}..removeWhere((key, value) => value.isEmpty));
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
return const Res(true);
|
return const Res(true);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -5,9 +5,11 @@ import 'package:flutter/gestures.dart';
|
|||||||
import 'package:flutter/material.dart' show Icons;
|
import 'package:flutter/material.dart' show Icons;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||||
|
import 'package:pixes/appdata.dart';
|
||||||
import 'package:pixes/components/animated_image.dart';
|
import 'package:pixes/components/animated_image.dart';
|
||||||
import 'package:pixes/components/loading.dart';
|
import 'package:pixes/components/loading.dart';
|
||||||
import 'package:pixes/components/message.dart';
|
import 'package:pixes/components/message.dart';
|
||||||
|
import 'package:pixes/components/page_route.dart';
|
||||||
import 'package:pixes/components/title_bar.dart';
|
import 'package:pixes/components/title_bar.dart';
|
||||||
import 'package:pixes/foundation/app.dart';
|
import 'package:pixes/foundation/app.dart';
|
||||||
import 'package:pixes/foundation/image_provider.dart';
|
import 'package:pixes/foundation/image_provider.dart';
|
||||||
@@ -17,6 +19,7 @@ import 'package:pixes/pages/comments_page.dart';
|
|||||||
import 'package:pixes/pages/image_page.dart';
|
import 'package:pixes/pages/image_page.dart';
|
||||||
import 'package:pixes/pages/search_page.dart';
|
import 'package:pixes/pages/search_page.dart';
|
||||||
import 'package:pixes/pages/user_info_page.dart';
|
import 'package:pixes/pages/user_info_page.dart';
|
||||||
|
import 'package:pixes/utils/block.dart';
|
||||||
import 'package:pixes/utils/translation.dart';
|
import 'package:pixes/utils/translation.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
@@ -143,6 +146,7 @@ class IllustPage extends StatefulWidget {
|
|||||||
class _IllustPageState extends State<IllustPage> {
|
class _IllustPageState extends State<IllustPage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var isBlocked = checkIllusts([widget.illust]).isEmpty;
|
||||||
return buildKeyboardListener(ColoredBox(
|
return buildKeyboardListener(ColoredBox(
|
||||||
color: FluentTheme.of(context).micaBackgroundColor,
|
color: FluentTheme.of(context).micaBackgroundColor,
|
||||||
child: SizedBox.expand(
|
child: SizedBox.expand(
|
||||||
@@ -151,6 +155,7 @@ class _IllustPageState extends State<IllustPage> {
|
|||||||
child: LayoutBuilder(builder: (context, constrains) {
|
child: LayoutBuilder(builder: (context, constrains) {
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
|
if (!isBlocked)
|
||||||
Positioned(
|
Positioned(
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
@@ -158,12 +163,22 @@ class _IllustPageState extends State<IllustPage> {
|
|||||||
top: 0,
|
top: 0,
|
||||||
child: buildBody(constrains.maxWidth, constrains.maxHeight),
|
child: buildBody(constrains.maxWidth, constrains.maxHeight),
|
||||||
),
|
),
|
||||||
|
if (!isBlocked)
|
||||||
_BottomBar(
|
_BottomBar(
|
||||||
widget.illust,
|
widget.illust,
|
||||||
constrains.maxHeight,
|
constrains.maxHeight,
|
||||||
constrains.maxWidth,
|
constrains.maxWidth,
|
||||||
favoriteCallback: widget.favoriteCallback,
|
favoriteCallback: widget.favoriteCallback,
|
||||||
|
updateCallback: () => setState(() {}),
|
||||||
),
|
),
|
||||||
|
if (isBlocked)
|
||||||
|
const Positioned.fill(
|
||||||
|
child: Center(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
"This artwork is blocked",
|
||||||
|
)),
|
||||||
|
))
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
@@ -306,10 +321,12 @@ class _IllustPageState extends State<IllustPage> {
|
|||||||
|
|
||||||
class _BottomBar extends StatefulWidget {
|
class _BottomBar extends StatefulWidget {
|
||||||
const _BottomBar(this.illust, this.height, this.width,
|
const _BottomBar(this.illust, this.height, this.width,
|
||||||
{this.favoriteCallback});
|
{this.favoriteCallback, this.updateCallback});
|
||||||
|
|
||||||
final void Function(bool)? favoriteCallback;
|
final void Function(bool)? favoriteCallback;
|
||||||
|
|
||||||
|
final void Function()? updateCallback;
|
||||||
|
|
||||||
final Illust illust;
|
final Illust illust;
|
||||||
|
|
||||||
final double height;
|
final double height;
|
||||||
@@ -378,8 +395,9 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handlePointerCancel() {
|
void _handlePointerCancel() {
|
||||||
if (animationController.value == 1 || animationController.value == 0)
|
if (animationController.value == 1 || animationController.value == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (animationController.value >= 0.5) {
|
if (animationController.value >= 0.5) {
|
||||||
animationController.forward();
|
animationController.forward();
|
||||||
} else {
|
} else {
|
||||||
@@ -876,7 +894,9 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildMoreActions() {
|
Widget buildMoreActions() {
|
||||||
return Row(
|
return Wrap(
|
||||||
|
runSpacing: 4,
|
||||||
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Button(
|
Button(
|
||||||
onPressed: () => favorite("private"),
|
onPressed: () => favorite("private"),
|
||||||
@@ -913,10 +933,7 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
).fixWidth(96),
|
||||||
const SizedBox(
|
|
||||||
width: 6,
|
|
||||||
),
|
|
||||||
Button(
|
Button(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Share.share(
|
Share.share(
|
||||||
@@ -937,10 +954,7 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
).fixWidth(96),
|
||||||
const SizedBox(
|
|
||||||
width: 6,
|
|
||||||
),
|
|
||||||
Button(
|
Button(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
var text = "https://pixiv.net/artworks/${widget.illust.id}";
|
var text = "https://pixiv.net/artworks/${widget.illust.id}";
|
||||||
@@ -959,10 +973,7 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
).fixWidth(96),
|
||||||
const SizedBox(
|
|
||||||
width: 6,
|
|
||||||
),
|
|
||||||
Button(
|
Button(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.to(() => _RelatedIllustsPage(widget.illust.id.toString()));
|
context.to(() => _RelatedIllustsPage(widget.illust.id.toString()));
|
||||||
@@ -979,12 +990,189 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
).fixWidth(96),
|
||||||
|
Button(
|
||||||
|
onPressed: () async {
|
||||||
|
await Navigator.of(context)
|
||||||
|
.push(SideBarRoute(_BlockingPage(widget.illust)));
|
||||||
|
if (mounted) {
|
||||||
|
widget.updateCallback?.call();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
height: 28,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(MdIcons.block, size: 18),
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
),
|
),
|
||||||
|
Text("Block".tl)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).fixWidth(96),
|
||||||
],
|
],
|
||||||
).paddingHorizontal(2).paddingBottom(4);
|
).paddingHorizontal(2).paddingBottom(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _BlockingPage extends StatefulWidget {
|
||||||
|
const _BlockingPage(this.illust);
|
||||||
|
|
||||||
|
final Illust illust;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_BlockingPage> createState() => __BlockingPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class __BlockingPageState extends State<_BlockingPage> {
|
||||||
|
List<int> blockedTags = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
TitleBar(title: "Block".tl),
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
padding: EdgeInsets.only(bottom: context.padding.bottom),
|
||||||
|
itemCount: widget.illust.tags.length + 2,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == widget.illust.tags.length + 1) {
|
||||||
|
return buildSubmit();
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = index == 0
|
||||||
|
? widget.illust.author.name
|
||||||
|
: widget.illust.tags[index - 1].name;
|
||||||
|
|
||||||
|
var subTitle = index == 0
|
||||||
|
? "author"
|
||||||
|
: widget.illust.tags[index - 1].translatedName ?? "";
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||||
|
borderColor: blockedTags.contains(index)
|
||||||
|
? ColorScheme.of(context).outlineVariant
|
||||||
|
: ColorScheme.of(context).outlineVariant.withOpacity(0.2),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(text),
|
||||||
|
subtitle: Text(subTitle),
|
||||||
|
trailing: Button(
|
||||||
|
onPressed: () {
|
||||||
|
if (blockedTags.contains(index)) {
|
||||||
|
blockedTags.remove(index);
|
||||||
|
} else {
|
||||||
|
blockedTags.add(index);
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: blockedTags.contains(index)
|
||||||
|
? Text("Cancel".tl)
|
||||||
|
: Text("Block".tl))
|
||||||
|
.fixWidth(72),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var flyout = FlyoutController();
|
||||||
|
|
||||||
|
bool isSubmitting = false;
|
||||||
|
|
||||||
|
Widget buildSubmit() {
|
||||||
|
return FlyoutTarget(
|
||||||
|
controller: flyout,
|
||||||
|
child: FilledButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (this.blockedTags.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isSubmitting) return;
|
||||||
|
var blockedTags = <String>[];
|
||||||
|
var blockedUsers = <String>[];
|
||||||
|
for (var i in this.blockedTags) {
|
||||||
|
if (i == 0) {
|
||||||
|
blockedUsers.add(widget.illust.author.id.toString());
|
||||||
|
} else {
|
||||||
|
blockedTags.add(widget.illust.tags[i - 1].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool addToAccount = false;
|
||||||
|
bool addToLocal = false;
|
||||||
|
if (appdata.account!.user.isPremium) {
|
||||||
|
await flyout.showFlyout(
|
||||||
|
navigatorKey: App.rootNavigatorKey.currentState,
|
||||||
|
builder: (context) {
|
||||||
|
return MenuFlyout(
|
||||||
|
items: [
|
||||||
|
MenuFlyoutItem(
|
||||||
|
text: Text("Local".tl),
|
||||||
|
onPressed: () {
|
||||||
|
addToLocal = true;
|
||||||
|
}),
|
||||||
|
MenuFlyoutItem(
|
||||||
|
text: Text("Account".tl),
|
||||||
|
onPressed: () {
|
||||||
|
addToAccount = true;
|
||||||
|
}),
|
||||||
|
MenuFlyoutItem(
|
||||||
|
text: Text("Both".tl),
|
||||||
|
onPressed: () {
|
||||||
|
addToLocal = true;
|
||||||
|
addToAccount = true;
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addToLocal = true;
|
||||||
|
}
|
||||||
|
if (addToAccount) {
|
||||||
|
setState(() {
|
||||||
|
isSubmitting = true;
|
||||||
|
});
|
||||||
|
var res =
|
||||||
|
await Network().editMute(blockedTags, blockedUsers, [], []);
|
||||||
|
setState(() {
|
||||||
|
isSubmitting = false;
|
||||||
|
});
|
||||||
|
if (res.error) {
|
||||||
|
if (mounted) {
|
||||||
|
context.showToast(message: "Network Error");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addToLocal) {
|
||||||
|
for (var tag in blockedTags) {
|
||||||
|
appdata.settings['blockTags'].add(tag);
|
||||||
|
}
|
||||||
|
for (var user in blockedUsers) {
|
||||||
|
appdata.settings['blockTags'].add('user:$user');
|
||||||
|
}
|
||||||
|
appdata.writeSettings();
|
||||||
|
}
|
||||||
|
if (mounted) {
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: isSubmitting
|
||||||
|
? const ProgressRing(
|
||||||
|
strokeWidth: 1.6,
|
||||||
|
).fixWidth(18).fixHeight(18).toAlign(Alignment.center)
|
||||||
|
: Text("Submit".tl),
|
||||||
|
).fixWidth(96).fixHeight(28),
|
||||||
|
).toAlign(Alignment.center).paddingTop(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class IllustPageWithId extends StatefulWidget {
|
class IllustPageWithId extends StatefulWidget {
|
||||||
const IllustPageWithId(this.id, {super.key});
|
const IllustPageWithId(this.id, {super.key});
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@ import 'package:fluent_ui/fluent_ui.dart';
|
|||||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||||
import 'package:pixes/appdata.dart';
|
import 'package:pixes/appdata.dart';
|
||||||
import 'package:pixes/components/loading.dart';
|
import 'package:pixes/components/loading.dart';
|
||||||
import 'package:pixes/components/message.dart';
|
|
||||||
import 'package:pixes/components/novel.dart';
|
import 'package:pixes/components/novel.dart';
|
||||||
import 'package:pixes/components/page_route.dart';
|
import 'package:pixes/components/page_route.dart';
|
||||||
import 'package:pixes/components/user_preview.dart';
|
import 'package:pixes/components/user_preview.dart';
|
||||||
@@ -128,7 +127,6 @@ class _SearchPageState extends State<SearchPage> {
|
|||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
optionController.showFlyout(
|
optionController.showFlyout(
|
||||||
navigatorKey: App.rootNavigatorKey.currentState,
|
|
||||||
placementMode: FlyoutPlacementMode.bottomCenter,
|
placementMode: FlyoutPlacementMode.bottomCenter,
|
||||||
builder: buildSearchOption,
|
builder: buildSearchOption,
|
||||||
);
|
);
|
||||||
|
@@ -134,7 +134,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
"Download Path".tl,
|
"Download Path".tl,
|
||||||
"downloadPath",
|
"downloadPath",
|
||||||
check: (text) {
|
check: (text) {
|
||||||
if(!Directory(text).havePermission()) {
|
if (!Directory(text).havePermission()) {
|
||||||
return "No permission".tl;
|
return "No permission".tl;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -182,23 +182,30 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
buildItem(
|
buildItem(
|
||||||
title: "Github",
|
title: "Github",
|
||||||
action: IconButton(
|
action: IconButton(
|
||||||
icon: const Icon(MdIcons.open_in_new, size: 18,),
|
icon: const Icon(
|
||||||
|
MdIcons.open_in_new,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
launchUrlString("https://github.com/wgh136/pixes"),
|
launchUrlString("https://github.com/wgh136/pixes"),
|
||||||
)),
|
)),
|
||||||
buildItem(
|
buildItem(
|
||||||
title: "Telegram",
|
title: "Telegram",
|
||||||
action: IconButton(
|
action: IconButton(
|
||||||
icon: const Icon(MdIcons.open_in_new, size: 18,),
|
icon: const Icon(
|
||||||
onPressed: () =>
|
MdIcons.open_in_new,
|
||||||
launchUrlString("https://t.me/pica_group"),
|
size: 18,
|
||||||
|
),
|
||||||
|
onPressed: () => launchUrlString("https://t.me/pica_group"),
|
||||||
)),
|
)),
|
||||||
buildItem(
|
buildItem(
|
||||||
title: "Logs",
|
title: "Logs",
|
||||||
action: IconButton(
|
action: IconButton(
|
||||||
icon: const Icon(MdIcons.open_in_new, size: 18,),
|
icon: const Icon(
|
||||||
onPressed: () => context.to(() => const LogsPage())
|
MdIcons.open_in_new,
|
||||||
)),
|
size: 18,
|
||||||
|
),
|
||||||
|
onPressed: () => context.to(() => const LogsPage()))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -219,6 +226,22 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
));
|
));
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
buildItem(
|
||||||
|
title: "Block(Account)".tl,
|
||||||
|
action: Button(
|
||||||
|
child: Text("Edit".tl).fixWidth(64),
|
||||||
|
onPressed: () {
|
||||||
|
launchUrlString("https://www.pixiv.net/setting_mute.php");
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
buildItem(
|
||||||
|
title: "Block(Local)".tl,
|
||||||
|
action: Button(
|
||||||
|
child: Text("Edit".tl).fixWidth(64),
|
||||||
|
onPressed: () {
|
||||||
|
context.to(() => const _BlockTagsPage());
|
||||||
|
},
|
||||||
|
)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -233,21 +256,27 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
action: DropDownButton(
|
action: DropDownButton(
|
||||||
title: Text(appdata.settings["theme"] ?? "System".tl),
|
title: Text(appdata.settings["theme"] ?? "System".tl),
|
||||||
items: [
|
items: [
|
||||||
MenuFlyoutItem(text: Text("System".tl), onPressed: () {
|
MenuFlyoutItem(
|
||||||
|
text: Text("System".tl),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
appdata.settings["theme"] = "System";
|
appdata.settings["theme"] = "System";
|
||||||
});
|
});
|
||||||
appdata.writeData();
|
appdata.writeData();
|
||||||
StateController.findOrNull(tag: "MyApp")?.update();
|
StateController.findOrNull(tag: "MyApp")?.update();
|
||||||
}),
|
}),
|
||||||
MenuFlyoutItem(text: Text("light".tl), onPressed: () {
|
MenuFlyoutItem(
|
||||||
|
text: Text("light".tl),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
appdata.settings["theme"] = "Light";
|
appdata.settings["theme"] = "Light";
|
||||||
});
|
});
|
||||||
appdata.writeData();
|
appdata.writeData();
|
||||||
StateController.findOrNull(tag: "MyApp")?.update();
|
StateController.findOrNull(tag: "MyApp")?.update();
|
||||||
}),
|
}),
|
||||||
MenuFlyoutItem(text: Text("dark".tl), onPressed: () {
|
MenuFlyoutItem(
|
||||||
|
text: Text("dark".tl),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
appdata.settings["theme"] = "Dark";
|
appdata.settings["theme"] = "Dark";
|
||||||
});
|
});
|
||||||
@@ -260,28 +289,36 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
action: DropDownButton(
|
action: DropDownButton(
|
||||||
title: Text(appdata.settings["language"] ?? "System"),
|
title: Text(appdata.settings["language"] ?? "System"),
|
||||||
items: [
|
items: [
|
||||||
MenuFlyoutItem(text: const Text("System"), onPressed: () {
|
MenuFlyoutItem(
|
||||||
|
text: const Text("System"),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
appdata.settings["language"] = "System";
|
appdata.settings["language"] = "System";
|
||||||
});
|
});
|
||||||
appdata.writeData();
|
appdata.writeData();
|
||||||
StateController.findOrNull(tag: "MyApp")?.update();
|
StateController.findOrNull(tag: "MyApp")?.update();
|
||||||
}),
|
}),
|
||||||
MenuFlyoutItem(text: const Text("English"), onPressed: () {
|
MenuFlyoutItem(
|
||||||
|
text: const Text("English"),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
appdata.settings["language"] = "English";
|
appdata.settings["language"] = "English";
|
||||||
});
|
});
|
||||||
appdata.writeData();
|
appdata.writeData();
|
||||||
StateController.findOrNull(tag: "MyApp")?.update();
|
StateController.findOrNull(tag: "MyApp")?.update();
|
||||||
}),
|
}),
|
||||||
MenuFlyoutItem(text: const Text("简体中文"), onPressed: () {
|
MenuFlyoutItem(
|
||||||
|
text: const Text("简体中文"),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
appdata.settings["language"] = "简体中文";
|
appdata.settings["language"] = "简体中文";
|
||||||
});
|
});
|
||||||
appdata.writeData();
|
appdata.writeData();
|
||||||
StateController.findOrNull(tag: "MyApp")?.update();
|
StateController.findOrNull(tag: "MyApp")?.update();
|
||||||
}),
|
}),
|
||||||
MenuFlyoutItem(text: const Text("繁體中文"), onPressed: () {
|
MenuFlyoutItem(
|
||||||
|
text: const Text("繁體中文"),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
appdata.settings["language"] = "繁體中文";
|
appdata.settings["language"] = "繁體中文";
|
||||||
});
|
});
|
||||||
@@ -416,3 +453,88 @@ ${"Some keywords will be replaced by the following rule:".tl}
|
|||||||
${"Multiple path separators will be automatically replaced with a single".tl}
|
${"Multiple path separators will be automatically replaced with a single".tl}
|
||||||
""";
|
""";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _BlockTagsPage extends StatefulWidget {
|
||||||
|
const _BlockTagsPage();
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_BlockTagsPage> createState() => __BlockTagsPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class __BlockTagsPageState extends State<_BlockTagsPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
TitleBar(
|
||||||
|
title: "Block".tl,
|
||||||
|
action: FilledButton(
|
||||||
|
child: Text("Add".tl),
|
||||||
|
onPressed: () {
|
||||||
|
var controller = TextEditingController();
|
||||||
|
|
||||||
|
void finish(BuildContext context) {
|
||||||
|
var text = controller.text;
|
||||||
|
if (text.isNotEmpty &&
|
||||||
|
!(appdata.settings["blockTags"] as List).contains(text)) {
|
||||||
|
setState(() {
|
||||||
|
appdata.settings["blockTags"].add(text);
|
||||||
|
});
|
||||||
|
appdata.writeSettings();
|
||||||
|
}
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: true,
|
||||||
|
builder: (context) {
|
||||||
|
return ContentDialog(
|
||||||
|
title: Text("Add".tl),
|
||||||
|
content: SizedBox(
|
||||||
|
width: 300,
|
||||||
|
height: 32,
|
||||||
|
child: TextBox(
|
||||||
|
controller: controller,
|
||||||
|
onSubmitted: (v) => finish(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
FilledButton(
|
||||||
|
child: Text("Submit".tl),
|
||||||
|
onPressed: () {
|
||||||
|
finish(context);
|
||||||
|
})
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: appdata.settings["blockTags"].length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(appdata.settings["blockTags"][index]),
|
||||||
|
trailing: Button(
|
||||||
|
child: Text("Delete".tl),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
(appdata.settings["blockTags"] as List).removeAt(index);
|
||||||
|
});
|
||||||
|
appdata.writeSettings();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import 'package:pixes/appdata.dart';
|
import 'package:pixes/appdata.dart';
|
||||||
import 'package:pixes/network/models.dart';
|
import 'package:pixes/network/models.dart';
|
||||||
|
|
||||||
void checkIllusts(List<Illust> illusts) {
|
List<Illust> checkIllusts(List<Illust> illusts) {
|
||||||
illusts.removeWhere((illust) {
|
illusts.removeWhere((illust) {
|
||||||
if (illust.isBlocked) {
|
if (illust.isBlocked) {
|
||||||
return true;
|
return true;
|
||||||
@@ -9,7 +9,7 @@ void checkIllusts(List<Illust> illusts) {
|
|||||||
if (appdata.settings["blockTags"] == null) {
|
if (appdata.settings["blockTags"] == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (appdata.settings["blockTags"].contains(illust.author.name)) {
|
if (appdata.settings["blockTags"].contains("user:${illust.author.name}")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (var tag in illust.tags) {
|
for (var tag in illust.tags) {
|
||||||
@@ -19,4 +19,5 @@ void checkIllusts(List<Illust> illusts) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
return illusts;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user