Unofficial Kavita client for mobile and desktop (in progress)
- Motivation
- About
- Template: Getting Started
- Setup
- Testing
- Building from Source (Advanced)
- Architecture
- Libraries
- Contributing
There is a lack of apps for self hosted services like Kavita and Audiobookshelf, this app provides some basic functionality for them.
A preview of the application is deployed to getboolean.github.io/subete_app.
- Supports Kavita 0.8
- Minimal OS Version:
- iOS: 13.0
- Android: 6.0 (SDK 23)
- MacOS: 10.14.6
- Windows 10
- Linux: Any modern distribution
- Made with Flutter
- Template by @getBoolean
- Add Environment Variables: ENVied Environment Variables section for details.
- Change App Icon: flutter_launcher_icons
- Change Splash Screen: flutter_native_splash
- Setup Codecov for the repository, see the Codecov documentation.
- Delete this
Template: Getting Startedsection from the README.
- Install puro Flutter Environment Manager
- Install Flutter stable using Puro
- Install Melos globally
- Install Mason CLI
- Run
melos bootstrapto install dependencies for all packages and generate env files.
- This project uses Mocktail to create mocks and fakes. Follow the instructions in the Mocktail README.
- Tests are located in the
testroot directory and each package. To run all tests, run the following command:
melos run test-
To run and build this app, you need to have Flutter SDK installed on your system. Check for any problems with the command below.
flutter doctor
-
Create/modify packages/env/local.env.
# required
KAVITA_BASE_URL=https://kavita.example.com
# Either of the following
# Option 1 (remove if unused)
KAVITA_API_KEY=key_here
# Option 2
KAVITA_USERNAME=username_here
KAVITA_PASSWORD=password_here
-
Initialize the Flutter project using melos.
flutter pub get dart pub global activate melos melos bootstrap
-
If you change environment variables after the above step, run these commands to update the code generated environment variables.
melos run env melos run generate:pkg # choose "env" when prompted -
Then, you can run the app normally with
flutter runor build the app executables with the following commands.-
iOS IPA
flutter build ios --release --no-codesign --dart-define FLUTTER_APP_FLAVOR=local --no-tree-shake-icons cd build/ios/iphoneos && rm -rf Payload && mkdir Payload && cd Payload && ln -s ../Runner.app && cd .. && zip -r subete-release.ipa Payload && cd ../../..
-
Android APK
flutter build apk --release --dart-define FLUTTER_APP_FLAVOR=local --no-tree-shake-icons cd build/app/outputs/flutter-apk && mv app-release.apk subete-release.apk
-
Windows MSIX
flutter build windows --dart-define FLUTTER_APP_FLAVOR=local dart run msix:create --build-windows false cd build/windows/x64/runner/Release && mv subete.msix subete-release.msix
-
MacOS DMG
git config --global core.longpaths true brew install create-dmg flutter build macos --release --dart-define FLUTTER_APP_FLAVOR=local --no-tree-shake-icons create-dmg --volname subete-release-macos --window-pos 200 120 --window-size 800 450 --icon-size 100 --app-drop-link 600 185 subete-release-macos.dmg build/macos/Build/Products/Release/subete.app -
Linux AppImage
sudo apt-get update sudo apt-get install webkit2gtk-4.1 clang cmake ninja-build pkg-config libgtk-3-dev mpv libmpv-dev dpkg-dev sudo apt install -y libfuse2 flutter build linux --release --dart-define FLUTTER_APP_FLAVOR=local curl -JOL <https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage> chmod a+x appimagetool-x86_64.AppImage mv appimagetool-x86_64.AppImage appimagetool mv build/linux/x64/release/bundle/{subete,AppRun} cp linux/appimage/*build/linux/x64/release/bundle/ ./appimagetool build/linux/x64/release/bundle/ mv*.AppImage build/subete-release.AppImage
-
Flavors are used to provide different environment variables based on the current flavor. By default,
the app uses the "local" flavor. Run/build the app with --dart-define FLUTTER_APP_FLAVOR=<flavorname>
to change the flavor. The following flavors are supported:
local- Local development. The text banner changes to "Debug" when in debug mode, "Local" in profile mode, and hidden in release mode.dev- Development build not intended for release.beta- Beta build intended for release to testers.staging- Staging build intended for device integration testing.prod- Production build intended for release to stores.
This project uses the Riverpod App Architecture in a feature-first manner where each feature is a separate package in the lib/src/features/ folder. Each feature has its own layers, which separate the business logic from the UI.
The repository pattern consists of Repositories, DTOs, and Data Sources. Their jobs are the following:
- isolate domain models (or entities) from the implementation details of the data sources in the data layer.
- convert data transfer objects to validated entities that are understood by the domain layer
- (optionally) perform operations such as data caching.
Repository pattern use cases:
- talking to REST APIs
- talking to local or remote databases (e.g. Sembast, Hive, Firestore, etc.)
- talking to device-specific APIs (e.g. permissions, camera, location, etc.)
Domain Models, which consist of entity and value objects. It should solve domain-related problems.
The domain models can contain logic for mutating them in an immutable manner, but they should not contain any serialization.
- Note: it is a simple data classes that doesn't have access to repositories, services, or other objects that belong outside the domain layer.
- holds business logic
- manage the widget state
- interact with repositories in the data layer
Implements application-specific logic by accessing the relevant repositories as needed. The service classes are not concerned about:
- managing and updating the widget state (that's the job of the controller)
- data parsing and serialization (that's the job of the repositories)
This project uses Melos to manage the monorepo.
flutter pub get
# Install melos globally
dart pub global activate melos
# Setup local dependency overrides for packages in the monorepo
melos bootstrap
# Or if dart executables are not on your path
dart pub global run melos bootstrapPub:
melos run pub- Runpub getin all packages.melos run dart:pkg- Rundart pub getin the selected dart package.melos run flutter:pkg- Runflutter pub getin the selected flutter package.melos run upgrade- Runpub upgradein all packages.melos run upgrade:pkg- Runpub upgradein the selected package.
Code Generation:
dart run build_runner watch -d- Watch and generate code for the app, does not work with subpackagesmelos run generate- Runbuild_runner buildin all packages that depend onbuild_runner.melos run generate:pkg- Runbuild_runner buildfor a specific package (exceptenviedpackages).melos run watch:pkg- Runbuild_runner watchfor a specific package (exceptenviedpackages). It will not work if you choose "all" in the package selection prompt.melos run assets- Runassets_gen buildin all packages that depend onassets_gen.melos run assets:pkg- Runassets_gen buildfor a specific package.melos run env- Runbuild_runnerin all packages that depends onenvied.melos run env:pkg- Runbuild_runnerin a specific package that depends onenvied.melos run loc- Runflutter gen-l10nin the localization package to generate the localized strings from the arb files.
Tests:
melos run lint- Run dart analyzer and custom lints in all packages.melos run analyze- Rundart analyzein all packages.melos run custom_lint- Rundart run custom_lintin all packages.melos run test- Run all Flutter tests.melos run format- Rundart formatin all packages.melos run fix- Rundart fix --applyin all packages.melos run test- Run all tests in the project.melos run flutter_test- Run all Flutter tests in the project.melos run dart_test- Run all Dart tests in the project.melos run flutter_test:pkg- Run Flutter tests for a specific package.melos run dart_test:pkg- Run Dart tests for a specific (Dart only) package.
Environment variables are setup using ENVied in the env package. Environment variables need to be defined for debug, profile, and release modes.
- Copy the
*.env.examplefiles and remove the.exampleextension from them. - Add the values for the environment variables in the respective
.env*file.- Each key must be added to each
.env*file, unless a non null default value is added to the@EnviedFieldannotation. - It is recommended to use an empty string for the default and use
Env's getter to access the value.
- Each key must be added to each
- Update src/env/app_env_fields.dart
with the new environment variables for
AppEnvFieldsGeneratedandAppEnvFieldsNullable. - Add the new environment variables to the implementing
*Envclasses in the src/env directory.- It must be done for all even if only one
.envfile is planned to be used
- It must be done for all even if only one
- Optionally, add a
@EnviedFielddefaultValueor enableoptionalon the annotation for keys which are not required in all modes.
- Fork it https://github.com/getBoolean/subete_app/fork
- Create your feature branch (git checkout -b feature/fooBar)
- Commit your changes (git commit -am 'Add some fooBar')
- Push to the branch (git push origin feature/fooBar)
- Create a new Pull Request