mirror of
https://github.com/Iconica-Development/flutter_timetable.git
synced 2025-05-19 11:43:45 +02:00
Compare commits
9 commits
Author | SHA1 | Date | |
---|---|---|---|
|
79f31f2552 | ||
|
0136f84a10 | ||
|
333c189428 | ||
|
9bac97f831 | ||
|
8b333e7bb7 | ||
|
32b9f9f2c5 | ||
|
f031828067 | ||
|
651ed33cfc | ||
|
93b25c7db6 |
51 changed files with 792 additions and 53 deletions
23
.github/dependabot.yml
vendored
Normal file
23
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
updates:
|
||||||
|
# - package-ecosystem: "pub"
|
||||||
|
# directory: "/packages/flutter_timetable"
|
||||||
|
# schedule:
|
||||||
|
# interval: "weekly"
|
||||||
|
|
||||||
|
- package-ecosystem: "pub"
|
||||||
|
directory: "/packages/flutter_timetable_interface"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
|
||||||
|
- package-ecosystem: "pub"
|
||||||
|
directory: "/packages/flutter_timetable_firebase"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
|
||||||
|
- package-ecosystem: "pub"
|
||||||
|
directory: "/packages/flutter_timetable_view"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
|
14
.github/workflows/component-documentation.yml
vendored
Normal file
14
.github/workflows/component-documentation.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
name: Iconica Standard Component Documentation Workflow
|
||||||
|
# Workflow Caller version: 1.0.0
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-iconica-component-documentation-workflow:
|
||||||
|
uses: Iconica-Development/.github/.github/workflows/component-documentation.yml@master
|
||||||
|
secrets: inherit
|
||||||
|
permissions: write-all
|
12
.github/workflows/flutter.yml
vendored
12
.github/workflows/flutter.yml
vendored
|
@ -1,12 +0,0 @@
|
||||||
name: Iconica Standard Component CI Workflow
|
|
||||||
# Workflow Caller version: 1.0.0
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
call-global-iconica-workflow:
|
|
||||||
uses: Iconica-Development/.github/.github/workflows/component-ci.yml@master
|
|
||||||
secrets: inherit
|
|
||||||
permissions: write-all
|
|
14
.github/workflows/melos-ci.yml
vendored
Normal file
14
.github/workflows/melos-ci.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
name: Iconica Standard Melos CI Workflow
|
||||||
|
# Workflow Caller version: 1.0.0
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-global-iconica-workflow:
|
||||||
|
uses: Iconica-Development/.github/.github/workflows/melos-ci.yml@master
|
||||||
|
secrets: inherit
|
||||||
|
permissions: write-all
|
||||||
|
with:
|
||||||
|
subfolder: '.' # add optional subfolder to run workflow in
|
17
.gitignore
vendored
17
.gitignore
vendored
|
@ -23,12 +23,23 @@ migrate_working_dir/
|
||||||
|
|
||||||
# Flutter/Dart/Pub related
|
# Flutter/Dart/Pub related
|
||||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
/pubspec.lock
|
pubspec.lock
|
||||||
**/doc/api/
|
**/doc/api/
|
||||||
.dart_tool/
|
.dart_tool/
|
||||||
.packages
|
.packages
|
||||||
build/
|
build/
|
||||||
.metadata
|
.metadata
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
|
||||||
|
android/
|
||||||
|
ios/
|
||||||
|
web/
|
||||||
|
linux/
|
||||||
|
macos/
|
||||||
|
windows/
|
||||||
|
|
||||||
|
pubspec_overrides.yaml
|
||||||
|
|
||||||
example/android/
|
example/android/
|
||||||
example/ios/
|
example/ios/
|
||||||
|
@ -36,3 +47,7 @@ example/web/
|
||||||
example/linux/
|
example/linux/
|
||||||
example/macos/
|
example/macos/
|
||||||
example/windows/
|
example/windows/
|
||||||
|
|
||||||
|
# FVM Version Cache
|
||||||
|
.fvm/
|
||||||
|
.fvmrc
|
||||||
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -26,3 +26,17 @@
|
||||||
## [1.3.0] - 8 November 2023
|
## [1.3.0] - 8 November 2023
|
||||||
|
|
||||||
* Add the option for setting an offset for the hours so that the first hour is not 00:00 but 08:00 for example and the last hour can be after 24:00.
|
* Add the option for setting an offset for the hours so that the first hour is not 00:00 but 08:00 for example and the last hour can be after 24:00.
|
||||||
|
|
||||||
|
## [1.4.0] - 13 November 2023
|
||||||
|
|
||||||
|
* Add the option for sorting the blocks by their id.
|
||||||
|
|
||||||
|
## [2.0.0] - 03 December 2023
|
||||||
|
|
||||||
|
* Create Melos variant of the component where there are multiple packages in the same repository.
|
||||||
|
|
||||||
|
* Added the option to sort on the starttime of an event.
|
||||||
|
|
||||||
|
## [3.0.0] - 11 July 2024
|
||||||
|
|
||||||
|
* Rename main entry point to flutter_timetable
|
||||||
|
|
198
CONTRIBUTING.md
Normal file
198
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
First off, thanks for taking the time to contribute! ❤️
|
||||||
|
|
||||||
|
All types of contributions are encouraged and valued.
|
||||||
|
See the [Table of Contents](#table-of-contents) for different ways to help and details about how we handle them.
|
||||||
|
Please make sure to read the relevant section before making your contribution.
|
||||||
|
It will make it a lot easier for us maintainers and smooth out the experience for all involved.
|
||||||
|
Iconica looks forward to your contributions. 🎉
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
- [Code of conduct](#code-of-conduct)
|
||||||
|
- [I Have a Question](#i-have-a-question)
|
||||||
|
- [I Want To Contribute](#i-want-to-contribute)
|
||||||
|
- [Reporting Bugs](#reporting-bugs)
|
||||||
|
- [Contributing code](#contributing-code)
|
||||||
|
|
||||||
|
## Code of conduct
|
||||||
|
|
||||||
|
### Legal notice
|
||||||
|
|
||||||
|
When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
|
||||||
|
All accepted pull requests and other additions to this project will be considered intellectual property of Iconica.
|
||||||
|
|
||||||
|
All repositories should be kept clean of jokes, easter eggs and other unnecessary additions.
|
||||||
|
|
||||||
|
## I have a question
|
||||||
|
|
||||||
|
If you want to ask a question, we assume that you have read the available documentation found within the code.
|
||||||
|
Before you ask a question, it is best to search for existing issues that might help you.
|
||||||
|
In case you have found a suitable issue but still need clarification, you can ask your question
|
||||||
|
It is also advisable to search the internet for answers first.
|
||||||
|
|
||||||
|
If you then still feel the need to ask a question and need clarification, we recommend the following:
|
||||||
|
|
||||||
|
- Open an issue.
|
||||||
|
- Provide as much context as you can about what you're running into.
|
||||||
|
|
||||||
|
We will then take care of the issue as soon as possible.
|
||||||
|
|
||||||
|
## I want to contribute
|
||||||
|
|
||||||
|
### Reporting bugs
|
||||||
|
|
||||||
|
<!-- omit in toc -->
|
||||||
|
|
||||||
|
**Before submitting a bug report**
|
||||||
|
|
||||||
|
A good bug report shouldn't leave others needing to chase you up for more information.
|
||||||
|
Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report.
|
||||||
|
Please complete the following steps in advance to help us fix any potential bug as fast as possible.
|
||||||
|
|
||||||
|
- Make sure that you are using the latest version.
|
||||||
|
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (If you are looking for support, you might want to check [this section](#i-have-a-question)).
|
||||||
|
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error.
|
||||||
|
- Also make sure to search the internet (including Stack Overflow) to see if users outside of Iconica have discussed the issue.
|
||||||
|
- Collect information about the bug:
|
||||||
|
- Stack trace (Traceback)
|
||||||
|
- OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
|
||||||
|
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
|
||||||
|
- Time and date of occurance
|
||||||
|
- Describe the expected result and actual result
|
||||||
|
- Can you reliably reproduce the issue? And can you also reproduce it with older versions? Describe all steps that lead to the bug.
|
||||||
|
|
||||||
|
Once it's filed:
|
||||||
|
|
||||||
|
- The project team will label the issue accordingly.
|
||||||
|
- A team member will try to reproduce the issue with your provided steps.
|
||||||
|
If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for additional information.
|
||||||
|
- If the team is able to reproduce the issue, it will be moved into the backlog, as well as marked with a priority, and the issue will be left to be [implemented by someone](#contributing-code).
|
||||||
|
|
||||||
|
### Contributing code
|
||||||
|
|
||||||
|
When you start working on your contribution, make sure you are aware of the relevant documentation and the functionality of the component you are working on.
|
||||||
|
|
||||||
|
When writing code, follow the style guidelines set by Dart: [Effective Dart](https://Dart.dev/guides/language/effective-Dart). This contains most information you will need to write clean Dart code that is well documented.
|
||||||
|
|
||||||
|
**Documentation**
|
||||||
|
|
||||||
|
As Effective Dart indicates, documenting your public methods with Dart doc comments is recommended.
|
||||||
|
Aside from Effective Dart, we require specific information in the documentation of a method:
|
||||||
|
|
||||||
|
At the very least, your documentation should first name what the code does, then followed below by requirements for calling the method, the result of the method.
|
||||||
|
Any references to internal variables or other methods should be done through [var] to indicate a reference.
|
||||||
|
|
||||||
|
If the method or class is complex enough (determined by the reviewers) an example is required.
|
||||||
|
If unsure, add an example in the docs using code blocks.
|
||||||
|
|
||||||
|
For classes and methods, document the individual parameters with their implications.
|
||||||
|
|
||||||
|
> Tip: Remember that the shortest documentation can be written by having good descriptive names in the first place.
|
||||||
|
|
||||||
|
An example:
|
||||||
|
|
||||||
|
````Dart
|
||||||
|
library iconica_utilities.bidirectional_sorter;
|
||||||
|
|
||||||
|
part 'sorter.Dart';
|
||||||
|
part 'enum.Dart';
|
||||||
|
|
||||||
|
/// Generic sort method, allow sorting of list with primitives or complex types.
|
||||||
|
/// Uses [SortDirection] to determine the direction, either Ascending or Descending,
|
||||||
|
/// Gets called on [List] toSort of type [T] which cannot be shorter than 2.
|
||||||
|
/// Optionally for complex types a [Comparable] [Function] can be given to compare complex types.
|
||||||
|
/// ```
|
||||||
|
/// List<TestObject> objects = [];
|
||||||
|
/// for (int i = 0; i < 10; i++) {
|
||||||
|
/// objects.add(TestObject(name: "name", id: i));
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// sort<TestObject>(
|
||||||
|
/// SortDirection.descending, objects, (object) => object.id);
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// In the above example a list of TestObjects is created, and then sorted in descending order.
|
||||||
|
/// If the implementation of TestObject is as following:
|
||||||
|
/// ```
|
||||||
|
/// class TestObject {
|
||||||
|
/// final String name;
|
||||||
|
/// final int id;
|
||||||
|
///
|
||||||
|
/// TestObject({required this.name, required this.id});
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// And the list is logged to the console, the following will appear:
|
||||||
|
/// ```
|
||||||
|
/// [name9, name8, name7, name6, name5, name4, name3, name2, name1, name0]
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
void sort<T>(
|
||||||
|
/// Determines the sorting direction, can be either Ascending or Descending
|
||||||
|
SortDirection sortDirection,
|
||||||
|
|
||||||
|
/// Incoming list, which gets sorted
|
||||||
|
List<T> toSort, [
|
||||||
|
|
||||||
|
/// Optional comparable, which is only necessary for complex types
|
||||||
|
SortFieldGetter<T>? sortValueCallback,
|
||||||
|
]) {
|
||||||
|
if (toSort.length < 2) return;
|
||||||
|
assert(
|
||||||
|
toSort.whereType<Comparable>().isNotEmpty || sortValueCallback != null);
|
||||||
|
BidirectionalSorter<T>(
|
||||||
|
sortInstructions: <SortInstruction<T>>[
|
||||||
|
SortInstruction(
|
||||||
|
sortValueCallback ?? (t) => t as Comparable, sortDirection),
|
||||||
|
],
|
||||||
|
).sort(toSort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// same functionality as [sort] but with the added functionality
|
||||||
|
/// of sorting multiple values
|
||||||
|
void sortMulti<T>(
|
||||||
|
/// Incoming list, which gets sorted
|
||||||
|
List<T> toSort,
|
||||||
|
|
||||||
|
/// list of comparables to sort multiple values at once,
|
||||||
|
/// priority based on index
|
||||||
|
List<SortInstruction<T>> sortValueCallbacks,
|
||||||
|
) {
|
||||||
|
if (toSort.length < 2) return;
|
||||||
|
assert(sortValueCallbacks.isNotEmpty);
|
||||||
|
BidirectionalSorter<T>(
|
||||||
|
sortInstructions: sortValueCallbacks,
|
||||||
|
).sort(toSort);
|
||||||
|
}
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
|
**Tests**
|
||||||
|
|
||||||
|
For each public method that was created, excluding widgets, which contains any form of logic (e.g. Calculations, predicates or major side-effects) tests are required.
|
||||||
|
|
||||||
|
A set of tests is written for each method, covering at least each path within the method. For example:
|
||||||
|
|
||||||
|
```Dart
|
||||||
|
void foo() {
|
||||||
|
try {
|
||||||
|
var bar = doSomething();
|
||||||
|
if (bar) {
|
||||||
|
doSomethingElse();
|
||||||
|
} else {
|
||||||
|
doSomethingCool();
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
displayError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The method above should result in 3 tests:
|
||||||
|
|
||||||
|
1. A test for the path leading to displayError by the cause of an exception
|
||||||
|
2. A test for if bar is true, resulting in doSomethingElse()
|
||||||
|
3. A test for if bar is false, resulting in the doSomethingCool() method being called.
|
||||||
|
|
||||||
|
This means that we require 100% coverage of each method you test.
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2022 Iconica, All rights reserved.
|
Copyright (c) 2023 Iconica, All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ Please file any issues, bugs or feature request as an issue on our [GitHub](http
|
||||||
|
|
||||||
## Want to contribute
|
## Want to contribute
|
||||||
|
|
||||||
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_date_time_picker/pulls).
|
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](./CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_date_time_picker/pulls).
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
|
38
melos.yaml
Normal file
38
melos.yaml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
name: flutter_timetable
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- packages/**
|
||||||
|
|
||||||
|
command:
|
||||||
|
version:
|
||||||
|
branch: master
|
||||||
|
|
||||||
|
scripts:
|
||||||
|
lint:all:
|
||||||
|
run: dart run melos run analyze && dart run melos run format-check
|
||||||
|
description: Run all static analysis checks.
|
||||||
|
|
||||||
|
get:
|
||||||
|
run: |
|
||||||
|
melos exec -c 1 -- "flutter pub get"
|
||||||
|
melos exec --scope="*example*" -c 1 -- "flutter pub get"
|
||||||
|
|
||||||
|
upgrade:
|
||||||
|
run: melos exec -c 1 -- "flutter pub upgrade"
|
||||||
|
|
||||||
|
create:
|
||||||
|
run: melos exec --scope="*example*" -c 1 -- "flutter create ."
|
||||||
|
|
||||||
|
analyze:
|
||||||
|
run: |
|
||||||
|
dart run melos exec -c 1 -- \
|
||||||
|
flutter analyze --fatal-infos
|
||||||
|
description: Run `flutter analyze` for all packages.
|
||||||
|
|
||||||
|
format:
|
||||||
|
run: dart run melos exec dart format .
|
||||||
|
description: Run `dart format` for all packages.
|
||||||
|
|
||||||
|
format-check:
|
||||||
|
run: dart run melos exec dart format . --set-exit-if-changed
|
||||||
|
description: Run `dart format` checks for all packages.
|
1
packages/flutter_timetable_firebase/CHANGELOG.md
Symbolic link
1
packages/flutter_timetable_firebase/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../CHANGELOG.md
|
1
packages/flutter_timetable_firebase/LICENSE
Symbolic link
1
packages/flutter_timetable_firebase/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../LICENSE
|
1
packages/flutter_timetable_firebase/README.md
Symbolic link
1
packages/flutter_timetable_firebase/README.md
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../README.md
|
43
packages/flutter_timetable_firebase/example/.gitignore
vendored
Normal file
43
packages/flutter_timetable_firebase/example/.gitignore
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
migrate_working_dir/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# The .vscode folder contains launch configuration and tasks you configure in
|
||||||
|
# VS Code which you may wish to be included in version control, so this line
|
||||||
|
# is commented out by default.
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
**/ios/Flutter/.last_build_id
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Symbolication related
|
||||||
|
app.*.symbols
|
||||||
|
|
||||||
|
# Obfuscation related
|
||||||
|
app.*.map.json
|
||||||
|
|
||||||
|
# Android Studio will place build artifacts here
|
||||||
|
/android/app/debug
|
||||||
|
/android/app/profile
|
||||||
|
/android/app/release
|
16
packages/flutter_timetable_firebase/example/README.md
Normal file
16
packages/flutter_timetable_firebase/example/README.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# example
|
||||||
|
|
||||||
|
A new Flutter project.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
This project is a starting point for a Flutter application.
|
||||||
|
|
||||||
|
A few resources to get you started if this is your first Flutter project:
|
||||||
|
|
||||||
|
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||||
|
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||||
|
|
||||||
|
For help getting started with Flutter development, view the
|
||||||
|
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||||
|
samples, guidance on mobile development, and a full API reference.
|
|
@ -0,0 +1,28 @@
|
||||||
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
|
# check for errors, warnings, and lints.
|
||||||
|
#
|
||||||
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
|
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||||
|
# invoked from the command line by running `flutter analyze`.
|
||||||
|
|
||||||
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
# The lint rules applied to this project can be customized in the
|
||||||
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
# included above or to enable additional rules. A list of all available lints
|
||||||
|
# and their documentation is published at https://dart.dev/lints.
|
||||||
|
#
|
||||||
|
# Instead of disabling a lint rule for the entire project in the
|
||||||
|
# section below, it can also be suppressed for a single line of code
|
||||||
|
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||||
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
|
# producing the lint.
|
||||||
|
rules:
|
||||||
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
23
packages/flutter_timetable_firebase/example/lib/main.dart
Normal file
23
packages/flutter_timetable_firebase/example/lib/main.dart
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:flutter_timetable_firebase/flutter_timetable_firebase.dart';
|
||||||
|
import 'package:flutter_timetable_interface/flutter_timetable_interface.dart';
|
||||||
|
|
||||||
|
class MyRosterModel extends TimetableEvent {
|
||||||
|
const MyRosterModel({
|
||||||
|
required super.end,
|
||||||
|
required super.start,
|
||||||
|
required super.entityId,
|
||||||
|
required super.eventId,
|
||||||
|
this.isSick = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool isSick;
|
||||||
|
}
|
||||||
|
|
||||||
|
final myRosterServiceProvider = Provider(
|
||||||
|
(ref) => FirebaseTimetableService<MyRosterModel>(
|
||||||
|
options: const FirebaseTimetableOptions(timetableCollectionName: 'roster'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
void main() {}
|
31
packages/flutter_timetable_firebase/example/pubspec.yaml
Normal file
31
packages/flutter_timetable_firebase/example/pubspec.yaml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
name: flutter_timetable_firebase_example
|
||||||
|
description: Timetable Widget
|
||||||
|
|
||||||
|
publish_to: 'none'
|
||||||
|
|
||||||
|
version: 1.1.0+2
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
cupertino_icons: ^1.0.2
|
||||||
|
flutter_timetable_firebase:
|
||||||
|
path: ../
|
||||||
|
flutter_timetable_interface:
|
||||||
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
version: ^2.0.0
|
||||||
|
hooks_riverpod: ^2.4.9
|
||||||
|
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
|
|
||||||
|
flutter:
|
||||||
|
uses-material-design: true
|
|
@ -0,0 +1,30 @@
|
||||||
|
// This is a basic Flutter widget test.
|
||||||
|
//
|
||||||
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
|
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||||
|
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||||
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import 'package:example/main.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
|
// Build our app and trigger a frame.
|
||||||
|
await tester.pumpWidget(const MyApp());
|
||||||
|
|
||||||
|
// Verify that our counter starts at 0.
|
||||||
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
expect(find.text('1'), findsNothing);
|
||||||
|
|
||||||
|
// Tap the '+' icon and trigger a frame.
|
||||||
|
await tester.tap(find.byIcon(Icons.add));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
// Verify that our counter has incremented.
|
||||||
|
expect(find.text('0'), findsNothing);
|
||||||
|
expect(find.text('1'), findsOneWidget);
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
library flutter_timetable_firebase;
|
||||||
|
|
||||||
|
export 'src/config/firebase_timetable_options.dart';
|
||||||
|
export 'src/services/firebase_timetable_service.dart';
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class FirebaseTimetableOptions {
|
||||||
|
const FirebaseTimetableOptions({
|
||||||
|
this.timetableCollectionName = 'timetable',
|
||||||
|
this.cachingStrategy = TimetableCachingStrategy.alwaysFetch,
|
||||||
|
});
|
||||||
|
// the collection reference name
|
||||||
|
final String timetableCollectionName;
|
||||||
|
|
||||||
|
/// Changes the Firebase Timetable Service to use different caching approaches
|
||||||
|
final TimetableCachingStrategy cachingStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TimetableCachingStrategy {
|
||||||
|
// Everytime the timetable is requested it will be fetched from the database
|
||||||
|
alwaysFetch,
|
||||||
|
// if you use fetchOnce the timetable events will be fetched only once
|
||||||
|
fetchOnce,
|
||||||
|
// will first be fetched and after that updates will be listened to
|
||||||
|
fetchOnceAndListen,
|
||||||
|
// if you use listen the timetable events will be updated in real time
|
||||||
|
listen,
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_timetable_firebase/src/config/firebase_timetable_options.dart';
|
||||||
|
import 'package:flutter_timetable_interface/flutter_timetable_interface.dart';
|
||||||
|
|
||||||
|
class FirebaseTimetableService<Event extends TimetableEvent>
|
||||||
|
with ChangeNotifier
|
||||||
|
implements TimetableService<Event> {
|
||||||
|
FirebaseTimetableService({
|
||||||
|
FirebaseApp? app,
|
||||||
|
options = const FirebaseTimetableOptions(),
|
||||||
|
}) {
|
||||||
|
var appInstance = app ?? Firebase.app();
|
||||||
|
_db = FirebaseFirestore.instanceFor(app: appInstance);
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
late FirebaseTimetableOptions _options;
|
||||||
|
late FirebaseFirestore _db;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> addEvent(Event event) async {
|
||||||
|
event.toJson();
|
||||||
|
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> checkForConflict(Event event, DateTime day) async {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deleteEvent(Event event) async {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Event>> fetchEventsForDay(DateTime day,
|
||||||
|
{String? category}) async {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Event> getEventsForDay(DateTime day, {String? category}) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> updateEvent(Event event) async {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
27
packages/flutter_timetable_firebase/pubspec.yaml
Normal file
27
packages/flutter_timetable_firebase/pubspec.yaml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
name: flutter_timetable_firebase
|
||||||
|
description: A new Flutter package project.
|
||||||
|
version: 2.0.0
|
||||||
|
repository: https://github.com/Iconica-Development/flutter_timetable
|
||||||
|
|
||||||
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=3.1.0 <4.0.0"
|
||||||
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
cloud_firestore: ^4.13.3
|
||||||
|
firebase_core: ^2.24.0
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter_timetable_interface:
|
||||||
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
version: ^2.0.0
|
||||||
|
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_lints: ^2.0.0
|
1
packages/flutter_timetable_interface/CHANGELOG.md
Symbolic link
1
packages/flutter_timetable_interface/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../CHANGELOG.md
|
1
packages/flutter_timetable_interface/LICENSE
Symbolic link
1
packages/flutter_timetable_interface/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../LICENSE
|
1
packages/flutter_timetable_interface/README.md
Symbolic link
1
packages/flutter_timetable_interface/README.md
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../README.md
|
|
@ -0,0 +1,4 @@
|
||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
|
@ -0,0 +1,8 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
library flutter_timetable_interface;
|
||||||
|
|
||||||
|
export 'src/models/timetable_event.dart';
|
||||||
|
export 'src/services/timetable_service.dart';
|
|
@ -0,0 +1,45 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class TimetableEvent {
|
||||||
|
/// The model used for a [Block] in a [TimeTable] which can contain a Widget.
|
||||||
|
const TimetableEvent({
|
||||||
|
required this.start,
|
||||||
|
required this.end,
|
||||||
|
required this.entityId,
|
||||||
|
required this.eventId,
|
||||||
|
this.category,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The date at which the event starts
|
||||||
|
final DateTime start;
|
||||||
|
|
||||||
|
/// The date at which the event ends
|
||||||
|
final DateTime end;
|
||||||
|
|
||||||
|
/// The unique identifier of the event
|
||||||
|
/// This is used to store the events
|
||||||
|
final String eventId;
|
||||||
|
|
||||||
|
/// The identifier of the entity that the event belongs to
|
||||||
|
/// This is used to check for conflicts between entities
|
||||||
|
final String entityId;
|
||||||
|
|
||||||
|
/// This can be used to filter events
|
||||||
|
final String? category;
|
||||||
|
|
||||||
|
// tojson method and a factory fromJson contructor
|
||||||
|
Map<String, dynamic> toJson() => {};
|
||||||
|
|
||||||
|
factory TimetableEvent.fromJson(String eventId, Map<String, dynamic> json) =>
|
||||||
|
TimetableEvent(
|
||||||
|
start: json['start'],
|
||||||
|
end: json['end'],
|
||||||
|
entityId: json[''],
|
||||||
|
eventId: eventId,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
abstract class TimetableService<Event> with ChangeNotifier {
|
||||||
|
Future<List<Event>> fetchEventsForDay(DateTime day, {String? category});
|
||||||
|
List<Event> getEventsForDay(DateTime day, {String? category});
|
||||||
|
Future<void> addEvent(Event event);
|
||||||
|
Future<void> updateEvent(Event event);
|
||||||
|
Future<void> deleteEvent(Event event);
|
||||||
|
Future<bool> checkForConflict(Event event, DateTime day);
|
||||||
|
}
|
21
packages/flutter_timetable_interface/pubspec.yaml
Normal file
21
packages/flutter_timetable_interface/pubspec.yaml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
name: flutter_timetable_interface
|
||||||
|
description: A new Flutter package project.
|
||||||
|
version: 2.0.0
|
||||||
|
repository: https://github.com/Iconica-Development/flutter_timetable
|
||||||
|
|
||||||
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=3.1.0 <4.0.0"
|
||||||
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_lints: ^2.0.0
|
1
packages/flutter_timetable_view/CHANGELOG.md
Symbolic link
1
packages/flutter_timetable_view/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../CHANGELOG.md
|
1
packages/flutter_timetable_view/LICENSE
Symbolic link
1
packages/flutter_timetable_view/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../LICENSE
|
1
packages/flutter_timetable_view/README.md
Symbolic link
1
packages/flutter_timetable_view/README.md
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../README.md
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timetable/timetable.dart';
|
import 'package:flutter_timetable_view/flutter_timetable_view.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MaterialApp(home: TimetableDemo()));
|
runApp(const MaterialApp(home: TimetableDemo()));
|
||||||
|
@ -34,7 +34,7 @@ class _TimetableDemoState extends State<TimetableDemo> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
id: 1,
|
id: 3,
|
||||||
),
|
),
|
||||||
TimeBlock(
|
TimeBlock(
|
||||||
start: const TimeOfDay(hour: 10, minute: 0),
|
start: const TimeOfDay(hour: 10, minute: 0),
|
||||||
|
@ -50,7 +50,7 @@ class _TimetableDemoState extends State<TimetableDemo> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
childDimension: 300,
|
childDimension: 300,
|
||||||
id: 3,
|
id: 1,
|
||||||
),
|
),
|
||||||
TimeBlock(
|
TimeBlock(
|
||||||
start: const TimeOfDay(hour: 14, minute: 0),
|
start: const TimeOfDay(hour: 14, minute: 0),
|
||||||
|
@ -150,6 +150,7 @@ class _TimetableDemoState extends State<TimetableDemo> {
|
||||||
onOverScroll: () {},
|
onOverScroll: () {},
|
||||||
onUnderScroll: () {},
|
onUnderScroll: () {},
|
||||||
hoursOffset: 6,
|
hoursOffset: 6,
|
||||||
|
sortByIdAscending: true,
|
||||||
size: Size(size.width, size.height * 0.64),
|
size: Size(size.width, size.height * 0.64),
|
||||||
tableDirection: _horizontal ? Axis.horizontal : Axis.vertical,
|
tableDirection: _horizontal ? Axis.horizontal : Axis.vertical,
|
||||||
startHour: 0,
|
startHour: 0,
|
|
@ -1,4 +1,4 @@
|
||||||
name: timetable_example
|
name: flutter_timetable_view_example
|
||||||
description: Timetable Widget
|
description: Timetable Widget
|
||||||
|
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
|
@ -13,8 +13,10 @@ dependencies:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
flutter_timetable:
|
flutter_timetable_view:
|
||||||
path: ../
|
path: ../
|
||||||
|
flutter_timetable_interface:
|
||||||
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
|
@ -2,10 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
library timetable;
|
library flutter_timetable;
|
||||||
|
|
||||||
export 'src/models/table_theme.dart';
|
export 'src/models/table_theme.dart';
|
||||||
export 'src/models/time_block.dart';
|
|
||||||
export 'src/timetable.dart';
|
export 'src/timetable.dart';
|
||||||
export 'src/widgets/block.dart';
|
export 'src/widgets/block.dart';
|
||||||
export 'src/widgets/table.dart';
|
export 'src/widgets/table.dart';
|
||||||
|
export 'src/models/time_block.dart';
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timetable/src/models/time_block.dart';
|
import 'package:flutter_timetable_view/src/models/time_block.dart';
|
||||||
|
|
||||||
/// Combine blocks that have the same id and the same time.
|
/// Combine blocks that have the same id and the same time.
|
||||||
List<TimeBlock> combineBlocksWithId(List<TimeBlock> blocks) {
|
List<TimeBlock> combineBlocksWithId(List<TimeBlock> blocks) {
|
||||||
|
@ -39,6 +39,7 @@ List<TimeBlock> combineBlocksWithId(List<TimeBlock> blocks) {
|
||||||
return newBlocks;
|
return newBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Combines grouped blocks into one block.
|
||||||
void _combineGroupedBlocks(
|
void _combineGroupedBlocks(
|
||||||
List<List<TimeBlock>> groupedBlocks,
|
List<List<TimeBlock>> groupedBlocks,
|
||||||
List<TimeBlock> newBlocks,
|
List<TimeBlock> newBlocks,
|
||||||
|
@ -74,6 +75,10 @@ void _combineGroupedBlocks(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if a block with a certain id exists in the grouped blocks.
|
||||||
|
///
|
||||||
|
/// Returns true if a block with the same id, start time, and end time exists in the grouped blocks list.
|
||||||
|
/// Otherwise, returns false.
|
||||||
bool _checkIfBlockWithIdExists(
|
bool _checkIfBlockWithIdExists(
|
||||||
List<List<TimeBlock>> groupedBlocks,
|
List<List<TimeBlock>> groupedBlocks,
|
||||||
TimeBlock block,
|
TimeBlock block,
|
|
@ -6,11 +6,12 @@ import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_timetable/src/block_service.dart';
|
import 'package:flutter_timetable_view/src/block_service.dart';
|
||||||
import 'package:flutter_timetable/src/models/table_theme.dart';
|
import 'package:flutter_timetable_view/src/models/table_theme.dart';
|
||||||
import 'package:flutter_timetable/src/models/time_block.dart';
|
import 'package:flutter_timetable_view/src/models/time_block.dart';
|
||||||
import 'package:flutter_timetable/src/widgets/block.dart';
|
import 'package:flutter_timetable_view/src/widgets/block.dart';
|
||||||
import 'package:flutter_timetable/src/widgets/table.dart' as table;
|
|
||||||
|
import 'package:flutter_timetable_view/src/widgets/table.dart' as table;
|
||||||
|
|
||||||
class Timetable extends StatefulWidget {
|
class Timetable extends StatefulWidget {
|
||||||
/// [Timetable] widget that displays a timetable with [TimeBlock]s.
|
/// [Timetable] widget that displays a timetable with [TimeBlock]s.
|
||||||
|
@ -34,6 +35,8 @@ class Timetable extends StatefulWidget {
|
||||||
this.theme = const TableTheme(),
|
this.theme = const TableTheme(),
|
||||||
this.mergeBlocks = false,
|
this.mergeBlocks = false,
|
||||||
this.combineBlocks = true,
|
this.combineBlocks = true,
|
||||||
|
this.sortByIdAscending = false,
|
||||||
|
this.sortByStartTime = false,
|
||||||
this.onOverScroll,
|
this.onOverScroll,
|
||||||
this.onUnderScroll,
|
this.onUnderScroll,
|
||||||
this.scrollTriggerOffset = 120,
|
this.scrollTriggerOffset = 120,
|
||||||
|
@ -42,7 +45,12 @@ class Timetable extends StatefulWidget {
|
||||||
}) : assert(
|
}) : assert(
|
||||||
scrollTriggerOffset > scrollJumpToOffset,
|
scrollTriggerOffset > scrollJumpToOffset,
|
||||||
'ScrollTriggerOffset cannot be smaller'
|
'ScrollTriggerOffset cannot be smaller'
|
||||||
' then the scrollJumpToOffset.');
|
' then the scrollJumpToOffset.',
|
||||||
|
),
|
||||||
|
assert(
|
||||||
|
!(mergeBlocks && sortByIdAscending),
|
||||||
|
'mergeBlocks and sortByIdAscending'
|
||||||
|
' cannot be enabled at the same time.');
|
||||||
|
|
||||||
/// The Axis in which the table is layed out.
|
/// The Axis in which the table is layed out.
|
||||||
final Axis tableDirection;
|
final Axis tableDirection;
|
||||||
|
@ -92,6 +100,12 @@ class Timetable extends StatefulWidget {
|
||||||
/// If blocks have the same id and time they will be combined into one block.
|
/// If blocks have the same id and time they will be combined into one block.
|
||||||
final bool combineBlocks;
|
final bool combineBlocks;
|
||||||
|
|
||||||
|
/// Whether or not to sort blocks by their ID in ascending order.
|
||||||
|
final bool sortByIdAscending;
|
||||||
|
|
||||||
|
/// Whether or not to sort blocks by their StartTime.
|
||||||
|
final bool sortByStartTime;
|
||||||
|
|
||||||
/// The offset which trigger the jump to either the previous or next page. Can't be lower then [scrollJumpToOffset].
|
/// The offset which trigger the jump to either the previous or next page. Can't be lower then [scrollJumpToOffset].
|
||||||
final double scrollTriggerOffset;
|
final double scrollTriggerOffset;
|
||||||
|
|
||||||
|
@ -147,6 +161,12 @@ class _TimetableState extends State<Timetable> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compareTimeOfDay(TimeOfDay time1, TimeOfDay time2) {
|
||||||
|
var totalMinutes1 = time1.hour * 60 + time1.minute;
|
||||||
|
var totalMinutes2 = time2.hour * 60 + time2.minute;
|
||||||
|
return totalMinutes1.compareTo(totalMinutes2);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
if (widget.scrollController == null) {
|
if (widget.scrollController == null) {
|
||||||
|
@ -163,6 +183,18 @@ class _TimetableState extends State<Timetable> {
|
||||||
} else {
|
} else {
|
||||||
blocks = widget.timeBlocks;
|
blocks = widget.timeBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (widget.sortByIdAscending) {
|
||||||
|
// if the id is zero then put it at the end
|
||||||
|
blocks.sort((a, b) => (a.id != 0 ? a.id : double.infinity).compareTo(
|
||||||
|
(b.id != 0 ? b.id : double.infinity),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.sortByStartTime) {
|
||||||
|
blocks.sort((a, b) => compareTimeOfDay(a.start, b.start));
|
||||||
|
}
|
||||||
|
|
||||||
var linePadding = _calculateTableTextSize().width;
|
var linePadding = _calculateTableTextSize().width;
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: widget.size?.width,
|
width: widget.size?.width,
|
||||||
|
@ -343,7 +375,7 @@ class _TimetableState extends State<Timetable> {
|
||||||
widget.theme.timeStyle ?? Theme.of(context).textTheme.bodyLarge,
|
widget.theme.timeStyle ?? Theme.of(context).textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
textScaleFactor: MediaQuery.of(context).textScaleFactor,
|
textScaler: MediaQuery.of(context).textScaler,
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
)..layout())
|
)..layout())
|
||||||
.size;
|
.size;
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timetable/src/models/table_theme.dart';
|
import 'package:flutter_timetable_view/src/models/table_theme.dart';
|
||||||
|
|
||||||
class Table extends StatelessWidget {
|
class Table extends StatelessWidget {
|
||||||
/// The [Table] to draw an overview of timerange with corresponding hour lines
|
/// The [Table] to draw an overview of timerange with corresponding hour lines
|
22
packages/flutter_timetable_view/pubspec.yaml
Normal file
22
packages/flutter_timetable_view/pubspec.yaml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
name: flutter_timetable_view
|
||||||
|
description: Flutter package to create a Timetable Widget that display blocks of widgets inside a timetable.
|
||||||
|
version: 2.0.0
|
||||||
|
repository: https://github.com/Iconica-Development/flutter_timetable
|
||||||
|
|
||||||
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=3.2.0 <4.0.0"
|
||||||
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter_timetable_interface:
|
||||||
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
version: ^2.0.0
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
flutter_lints: ^2.0.0
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_timetable/src/block_service.dart';
|
import 'package:flutter_timetable_view/src/block_service.dart';
|
||||||
import 'package:flutter_timetable/timetable.dart';
|
import 'package:flutter_timetable_view/src/models/time_block.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('test combineBlocksWithId', () {
|
group('test combineBlocksWithId', () {
|
19
pubspec.yaml
19
pubspec.yaml
|
@ -1,19 +1,6 @@
|
||||||
name: flutter_timetable
|
name: flutter_timetable_workspace
|
||||||
description: Flutter package to create a Timetable Widget that display blocks of widgets inside a timetable.
|
|
||||||
version: 1.3.0
|
|
||||||
repository: https://github.com/Iconica-Development/timetable
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: '>=3.1.0 <4.0.0'
|
||||||
flutter: ">=1.17.0"
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
flutter:
|
|
||||||
sdk: flutter
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
melos: ^3.0.1
|
||||||
sdk: flutter
|
|
||||||
flutter_lints: ^2.0.0
|
|
||||||
|
|
||||||
flutter:
|
|
||||||
|
|
Loading…
Reference in a new issue