Skip to content
Open
Show file tree
Hide file tree
Changes from 14 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
35 changes: 35 additions & 0 deletions .github/workflows/test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,38 @@ jobs:

- name: Build iOS
run: flutter build ios --no-codesign

linux_build:
name: Linux executable
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Install Linux dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y libgtk-3-dev

- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.VERSION }}
cache: true

- name: Configure Flutter
run: |
flutter config --no-analytics
flutter config --enable-linux-desktop

- name: Get Flutter packages
run: flutter pub get

- name: Build Linux
run: flutter build --verbose linux --debug

- name: Store artifact
uses: actions/upload-artifact@v4
with:
name: linux-appbundle
path: build/linux/x64/debug/bundle/
12 changes: 6 additions & 6 deletions .metadata
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.

version:
revision: "d211f42860350d914a5ad8102f9ec32764dc6d06"
revision: "be698c48a6750c8cb8e61c740ca9991bb947aba2"
channel: "stable"

project_type: app
Expand All @@ -13,11 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
- platform: ios
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
- platform: linux
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2

# User provided section

Expand Down
3 changes: 2 additions & 1 deletion lib/core/helpers/backup/backup_general.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:flutter/material.dart';

import 'package:easy_localization/easy_localization.dart';
import 'package:filesystem_picker/filesystem_picker.dart';
import 'package:openreads/core/helpers/cross_platform/alert_dialog.dart';
import 'package:openreads/main.dart';
import 'package:openreads/ui/home_screen/home_screen.dart';
import 'package:openreads/ui/settings_screen/download_missing_covers_screen.dart';
Expand Down Expand Up @@ -167,7 +168,7 @@ class BackupGeneral {
context: context,
builder: (context) {
return Builder(builder: (context) {
return AlertDialog.adaptive(
return buildPlatformSpecificAlertDialog(
title: Text(
LocaleKeys.import_successful.tr(),
),
Expand Down
8 changes: 3 additions & 5 deletions lib/core/helpers/backup/backup_import.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ class BackupImport {
return;
}
}
} else if (Platform.isIOS) {
FilePickerResult? result = await FilePicker.platform.pickFiles(
} else {
FilePickerResult? pickedFile = await FilePicker.platform.pickFiles(
withData: true,
);

final file = result!.files.single;
final file = pickedFile!.files.single;

// iOS app was released when backup 5 was the latest
final infoFileVersion = _checkInfoFileVersion(file.bytes, tmpDir);
Expand All @@ -140,8 +140,6 @@ class BackupImport {
BackupGeneral.showInfoSnackbar(LocaleKeys.backup_not_valid.tr());
return;
}
} else {
return;
}

BackupGeneral.showInfoSnackbar(LocaleKeys.restore_successfull.tr());
Expand Down
3 changes: 2 additions & 1 deletion lib/core/helpers/backup/csv_import_goodreads.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:easy_localization/easy_localization.dart';

import 'package:openreads/core/constants/enums/enums.dart';
import 'package:openreads/core/helpers/backup/backup.dart';
import 'package:openreads/core/helpers/cross_platform/alert_dialog.dart';
import 'package:openreads/generated/locale_keys.g.dart';
import 'package:openreads/model/reading.dart';
import 'package:openreads/model/book.dart';
Expand Down Expand Up @@ -158,7 +159,7 @@ class CSVImportGoodreads {
return await showDialog<String>(
context: context,
builder: (context) {
return AlertDialog.adaptive(
return buildPlatformSpecificAlertDialog(
title: Text(
LocaleKeys.choose_not_finished_shelf.tr(),
),
Expand Down
36 changes: 36 additions & 0 deletions lib/core/helpers/cross_platform/alert_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'dart:io';

import 'package:flutter/material.dart';

Widget buildPlatformSpecificAlertDialog({
required Widget title,
Widget? content,
List<Widget>? actions,
MainAxisAlignment? actionsAlignment,
EdgeInsets? contentPadding,
RoundedRectangleBorder? shape,
}) {
if (Platform.isLinux) {
// For Linux, we use a standard AlertDialog. Maybe it'll work well for
// other desktop platforms too, not tested.
return AlertDialog(
title: title,
content: content,
actionsAlignment: actionsAlignment,
actions: actions,
contentPadding: contentPadding,
shape: shape,
);
} else {
// AlertDialog.adaptive is a standard helper function to choose iOS and
// Android.
return AlertDialog.adaptive(
title: title,
content: content,
actionsAlignment: actionsAlignment,
actions: actions,
contentPadding: contentPadding,
shape: shape,
);
}
}
25 changes: 20 additions & 5 deletions lib/core/helpers/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:blurhash/blurhash.dart' as blurhash;
import 'package:blurhash_ffi/blurhash_ffi.dart' as blurhash_ffi;
import 'package:image_cropper/image_cropper.dart';
import 'package:openreads/core/constants/constants.dart';
import 'package:openreads/generated/locale_keys.g.dart';
Expand All @@ -14,11 +15,25 @@ import 'package:openreads/main.dart';
import 'package:openreads/model/book.dart';

Future generateBlurHash(Uint8List bytes, BuildContext context) async {
final blurHashStringTmp = await blurhash.BlurHash.encode(
bytes,
Constants.blurHashX,
Constants.blurHashY,
);
String blurHashStringTmp;
if (Platform.isLinux) {
// blurhash_ffi expects an ImageProvider, so you need to convert bytes to MemoryImage
final imageProvider = MemoryImage(bytes);
blurHashStringTmp = await blurhash_ffi.BlurhashFFI.encode(
imageProvider,
componentX: Constants.blurHashX,
componentY: Constants.blurHashY,
);
} else if (Platform.isAndroid || Platform.isIOS) {
// blurhash.encode expects bytes and dimensions
blurHashStringTmp = await blurhash.BlurHash.encode(
bytes,
Constants.blurHashX,
Constants.blurHashY,
);
} else {
throw Exception('Unsupported platform for generating BlurHash');
}

if (!context.mounted) return;

Expand Down
7 changes: 7 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:openreads/core/constants/constants.dart';
import 'package:openreads/core/constants/locale.dart';
import 'package:openreads/core/helpers/locale_delegates/locale_delegates.dart';
Expand Down Expand Up @@ -49,6 +50,12 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();

// Using sqflite_common_ffi on windows or linux which requires setup
if (Platform.isLinux || Platform.isWindows) {
sqfliteFfiInit();
databaseFactoryOrNull = databaseFactoryFfi;
}

_setAndroidConfig();

HydratedBloc.storage = await HydratedStorage.build(
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/add_book_screen/add_book_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:loading_animation_widget/loading_animation_widget.dart';

import 'package:openreads/core/constants/constants.dart';
import 'package:openreads/core/constants/enums/enums.dart';
import 'package:openreads/core/helpers/cross_platform/alert_dialog.dart';
import 'package:openreads/core/helpers/helpers.dart';
import 'package:openreads/core/themes/app_theme.dart';
import 'package:openreads/generated/locale_keys.g.dart';
Expand Down Expand Up @@ -192,7 +193,7 @@ class _AddBookScreenState extends State<AddBookScreen> {
return showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog.adaptive(
return buildPlatformSpecificAlertDialog(
title: Text(
LocaleKeys.coverStillDownloaded.tr(),
),
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/add_book_screen/widgets/cover_view_edit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class _CoverViewEditState extends State<CoverViewEdit> {
);
},
);
} else if (Platform.isAndroid) {
} else {
showModalBottomSheet(
context: context,
isScrollControlled: true,
Expand Down
27 changes: 14 additions & 13 deletions lib/ui/add_book_screen/widgets/duck_duck_go_alert.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:openreads/core/constants/constants.dart';
import 'package:openreads/core/helpers/cross_platform/alert_dialog.dart';
import 'package:openreads/core/themes/app_theme.dart';
import 'package:openreads/generated/locale_keys.g.dart';
import 'package:shared_preferences/shared_preferences.dart';
Expand Down Expand Up @@ -37,27 +38,27 @@ class DuckDuckGoAlert extends StatelessWidget {

@override
Widget build(BuildContext context) {
return AlertDialog.adaptive(
return buildPlatformSpecificAlertDialog(
title: Text(
LocaleKeys.duckDuckGoWarning.tr(),
style: Platform.isAndroid ? const TextStyle(fontSize: 16) : null,
),
actionsAlignment: MainAxisAlignment.spaceBetween,
actions: [
Platform.isAndroid
? _buildAndroidNoButton(context)
: _buildIOSNoButton(context),
Platform.isAndroid
? _buildAndroidYesButton(context)
: _buildIOSYesButton(context),
Platform.isAndroid
? _buildAndroidYesAndDontShowButton(context)
: _buildIOSYesAndDontShowButton(context),
Platform.isIOS
? _buildIOSNoButton(context)
: _buildNonIOSNoButton(context),
Platform.isIOS
? _buildIOSYesButton(context)
: _buildNonIOSYesButton(context),
Platform.isIOS
? _buildIOSYesAndDontShowButton(context)
: _buildNonIOSYesAndDontShowButton(context),
],
);
}

Widget _buildAndroidYesButton(BuildContext context) {
Widget _buildNonIOSYesButton(BuildContext context) {
return FilledButton.tonal(
onPressed: () => _yesButtonAction(context),
style: FilledButton.styleFrom(
Expand All @@ -75,7 +76,7 @@ class DuckDuckGoAlert extends StatelessWidget {
);
}

Widget _buildAndroidYesAndDontShowButton(BuildContext context) {
Widget _buildNonIOSYesAndDontShowButton(BuildContext context) {
return FilledButton(
onPressed: () => _yesAndDontShowButtonAction(context),
style: FilledButton.styleFrom(
Expand All @@ -93,7 +94,7 @@ class DuckDuckGoAlert extends StatelessWidget {
);
}

Widget _buildAndroidNoButton(BuildContext context) {
Widget _buildNonIOSNoButton(BuildContext context) {
return FilledButton(
onPressed: () => _noButtonAction(context),
style: TextButton.styleFrom(
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/add_book_screen/widgets/reading_row.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class _ReadingRowState extends State<ReadingRow> {
},
);
});
} else if (Platform.isAndroid) {
} else {
final startDate = await showDatePicker(
context: context,
initialDate: widget.reading.startDate ?? DateTime.now(),
Expand Down Expand Up @@ -83,7 +83,7 @@ class _ReadingRowState extends State<ReadingRow> {
},
);
});
} else if (Platform.isAndroid) {
} else {
final finishDate = await showDatePicker(
context: context,
initialDate: widget.reading.finishDate ?? DateTime.now(),
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/add_book_screen/widgets/reading_time_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:openreads/core/helpers/cross_platform/alert_dialog.dart';
import 'package:openreads/core/themes/app_theme.dart';
import 'package:openreads/generated/locale_keys.g.dart';
import 'package:openreads/model/reading_time.dart';
Expand Down Expand Up @@ -133,7 +134,7 @@ class _BookReadingTimeField extends State<BookReadingTimeField> {
Future<String?> buildShowDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) => AlertDialog.adaptive(
builder: (BuildContext context) => buildPlatformSpecificAlertDialog(
title: Text(
LocaleKeys.set_custom_reading_time.tr(),
style: const TextStyle(fontSize: 20),
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/book_screen/widgets/book_screen_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:openreads/core/helpers/cross_platform/alert_dialog.dart';
import 'package:openreads/core/themes/app_theme.dart';
import 'package:openreads/generated/locale_keys.g.dart';
import 'package:openreads/logic/bloc/theme_bloc/theme_bloc.dart';
Expand All @@ -31,7 +32,7 @@ class BookScreenAppBar extends StatelessWidget implements PreferredSizeWidget {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog.adaptive(
return buildPlatformSpecificAlertDialog(
shape: Platform.isAndroid
? RoundedRectangleBorder(
borderRadius: BorderRadius.circular(cornerRadius),
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/book_screen/widgets/quick_rating_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:openreads/core/helpers/cross_platform/alert_dialog.dart';
import 'package:openreads/core/themes/app_theme.dart';
import 'package:openreads/generated/locale_keys.g.dart';
import 'package:openreads/ui/book_screen/widgets/widgets.dart';
Expand All @@ -19,7 +20,7 @@ class _QuickRatingDialogState extends State<QuickRatingDialog> {

@override
Widget build(BuildContext context) {
return AlertDialog.adaptive(
return buildPlatformSpecificAlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(cornerRadius),
),
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/home_screen/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class _HomeScreenState extends State<HomeScreen> {
return const SortBottomSheet();
},
);
} else if (Platform.isAndroid) {
} else {
showModalBottomSheet(
context: context,
isScrollControlled: true,
Expand Down Expand Up @@ -142,7 +142,7 @@ class _HomeScreenState extends State<HomeScreen> {
);
},
);
} else if (Platform.isAndroid) {
} else {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
Expand Down
Loading