import 'package:fluent_reader_lite/components/list_tile_group.dart';
import 'package:fluent_reader_lite/components/my_list_tile.dart';
import 'package:fluent_reader_lite/generated/l10n.dart';
import 'package:fluent_reader_lite/utils/colors.dart';
import 'package:fluent_reader_lite/utils/store.dart';
import 'package:fluent_reader_lite/utils/global.dart';
import 'package:fluent_reader_lite/utils/font_manager.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
class ReadingPage extends StatefulWidget {
@override
_ReadingPageState createState() => _ReadingPageState();
}
class _ReadingPageState extends State<ReadingPage> {
int _fontSize = Store.getArticleFontSize();
List<String> _customFontNames = [];
List<String> _availableFonts = [];
@override
void initState() {
super.initState();
_loadCustomFonts();
}
void _loadCustomFonts() async {
final customFonts = await FontManager.getInstalledCustomFonts();
setState(() {
_customFontNames = customFonts;
_availableFonts = [...FontManager.builtInFonts, ...customFonts];
});
}
void _showFontPicker(BuildContext context) {
showCupertinoModalPopup(
context: context,
builder: (context) => CupertinoActionSheet(
title: Text(S.of(context).selectFontFamily),
actions: _availableFonts.map((font) {
final isCustom = !FontManager.builtInFonts.contains(font);
final isSelected = Global.globalModel.fontFamily == font;
final isSystem = font == 'System';
return CupertinoActionSheetAction(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
FontManager.getFontDisplayName(font),
style: TextStyle(
fontFamily: isCustom || isSystem ? null : font,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
),
if (isSelected) Padding(
padding: EdgeInsets.only(left: 8),
child: Icon(Icons.done, size: 18, color: CupertinoColors.activeBlue),
),
],
),
if (!isSystem && !isCustom)
Text(
'The quick brown fox jumps over the lazy dog',
style: TextStyle(
fontFamily: font,
fontSize: 12,
color: CupertinoColors.systemGrey,
),
),
if (isCustom)
Text(
'(${S.of(context).uploadCustomFont})',
style: TextStyle(
fontSize: 12,
color: CupertinoColors.systemGrey,
),
),
],
),
onPressed: () {
Global.globalModel.fontFamily = font;
Navigator.pop(context);
setState(() {});
},
);
}).toList(),
cancelButton: CupertinoActionSheetAction(
child: Text(S.of(context).cancel),
onPressed: () => Navigator.pop(context),
),
),
);
}
void _uploadCustomFont() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['ttf', 'otf', 'woff', 'woff2'],
);
if (result != null && result.files.single.path != null) {
try {
final sourcePath = result.files.single.path!;
final fileName = result.files.single.name;
await FontManager.installCustomFont(sourcePath, fileName);
final fontName = fileName.split('.').first;
Global.globalModel.fontFamily = fontName;
_loadCustomFonts();
showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: Text(S.of(context).fontUploaded),
content: Text(S.of(context).customFontUploaded),
actions: [
CupertinoDialogAction(
child: Text('OK'),
onPressed: () => Navigator.pop(context),
),
],
),
);
} catch (e) {
showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: Text(S.of(context).fontUploadError),
content: Text('$e'),
actions: [
CupertinoDialogAction(
child: Text('OK'),
onPressed: () => Navigator.pop(context),
),
],
),
);
}
}
}
void _confirmDeleteFont(BuildContext context, String fontName) {
showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: Text(S.of(context).deleteFont),
content: Text(S.of(context).deleteFontConfirm),
actions: [
CupertinoDialogAction(
child: Text(S.of(context).cancel),
onPressed: () => Navigator.pop(context),
),
CupertinoDialogAction(
isDestructiveAction: true,
child: Text(S.of(context).confirm),
onPressed: () async {
Navigator.pop(context);
try {
await FontManager.removeCustomFont(fontName);
if (Global.globalModel.fontFamily == fontName) {
Global.globalModel.fontFamily = 'System';
Store.sp.remove(StoreKeys.CUSTOM_FONT_PATH);
}
_loadCustomFonts();
} catch (e) {
showCupertinoDialog(
context: context,
builder: (ctx) => CupertinoAlertDialog(
title: Text(S.of(ctx).fontUploadError),
content: Text('$e'),
actions: [
CupertinoDialogAction(
child: Text('OK'),
onPressed: () => Navigator.pop(ctx),
),
],
),
);
}
},
),
],
),
);
}
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
backgroundColor: MyColors.background,
navigationBar: CupertinoNavigationBar(
middle: Text(S.of(context).reading),
),
child: ListView(children: [
ListTileGroup([
MyListTile(
title: Text(S.of(context).fontSize),
trailing: Text(_fontSize.toString()),
trailingChevron: false,
withDivider: false,
),
MyListTile(
title: Expanded(child: CupertinoSlider(
min: 10,
max: 22,
divisions: 13,
value: _fontSize.toDouble(),
onChanged: (v) { setState(() { _fontSize = v.toInt(); }); },
onChangeEnd: (v) { Store.setArticleFontSize(v.toInt()); },
)),
trailingChevron: false,
withDivider: false,
),
], title: S.of(context).preferences),
ListTileGroup([
MyListTile(
title: Text(S.of(context).fontFamily),
trailing: Text(FontManager.getFontDisplayName(Global.globalModel.fontFamily)),
onTap: () => _showFontPicker(context),
),
MyListTile(
title: Text(S.of(context).uploadCustomFont),
trailing: Icon(CupertinoIcons.add),
onTap: _uploadCustomFont,
withDivider: _customFontNames.isNotEmpty,
),
..._customFontNames.map((fontName) => MyListTile(
title: Text(fontName),
trailing: GestureDetector(
onTap: () => _confirmDeleteFont(context, fontName),
child: Icon(CupertinoIcons.delete, color: CupertinoColors.destructiveRed, size: 20),
),
trailingChevron: false,
withDivider: fontName != _customFontNames.last,
)),
], title: S.of(context).fontSettings),
]),
);
}
}