Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4700e9ec5 | ||
|
|
4cbbad6c1a | ||
|
|
6bbc75fa94 | ||
|
|
b0bbad7f97 |
No files matched your search
@@ -350,21 +350,3 @@ hs_err_pid*
|
|||||||
|
|
||||||
*.idea*
|
*.idea*
|
||||||
**/.DS_store
|
**/.DS_store
|
||||||
|
|
||||||
# Fastlane (Play-Store-Upload)
|
|
||||||
android/fastlane/report.xml
|
|
||||||
android/fastlane/Preview.html
|
|
||||||
android/fastlane/play-service-account.json
|
|
||||||
android/fastlane/README.md.bak
|
|
||||||
# lokale Screenshots außerhalb der Fastlane-Metadaten
|
|
||||||
/screenshots/
|
|
||||||
# Fastlane-Bild-PNGs sind generierte Kopien; kanonisch/versioniert liegen die
|
|
||||||
# Screenshots unter materials/screenshots/. Nur die leeren Ordner (.gitkeep)
|
|
||||||
# bleiben eingecheckt, damit supply die Struktur vorfindet.
|
|
||||||
android/fastlane/metadata/android/**/images/**/*.png
|
|
||||||
|
|
||||||
# Fastlane (App-Store-Upload)
|
|
||||||
ios/fastlane/report.xml
|
|
||||||
ios/fastlane/Preview.html
|
|
||||||
ios/fastlane/app-store-connect-api-key.json
|
|
||||||
ios/fastlane/screenshots/**/*.jpg
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
# MarianumMobile Client
|
|
||||||
|
|
||||||
Flutter-App für die Schul-Community: Stundenplan, Ticker, Newsletter & Co. über das MarianumConnect-Backend, Nextcloud Talk + Files.
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
- **Flutter** (Dart >= 3.8)
|
|
||||||
- **State:** `flutter_bloc` + `hydrated_bloc` (persistente BLoCs pro Modul)
|
|
||||||
- **Navigation:** `persistent_bottom_nav_bar_v2` mit zentraler `AppRoutes`-Klasse als Single Entry Point
|
|
||||||
- **HTTP:** `dio`, lokales Caching via `localstore` (Generic `RequestCache<T>`)
|
|
||||||
- **Calendar:** `syncfusion_flutter_calendar`
|
|
||||||
- **Datum/Zeit:** `jiffy` – wird **nur** über die Extensions in `lib/extensions/date_time.dart` verwendet
|
|
||||||
- **Code-Gen:** `freezed`, `json_serializable`
|
|
||||||
|
|
||||||
## Ordnerstruktur
|
|
||||||
|
|
||||||
```
|
|
||||||
lib/
|
|
||||||
├── api/ HTTP-Layer pro Backend (marianumconnect/, marianumcloud/, mhsl/ Legacy, demo/)
|
|
||||||
├── session/ Session-Modell, SessionManager, SessionLifecycle, Konten-Index
|
|
||||||
├── state/app/modules/ BLoC pro Feature-Modul (timetable, chat, chat_list, files, ...)
|
|
||||||
├── state/app/infrastructure LoadableState<T>, DataLoader, geteilte BLoC-Bausteine
|
|
||||||
├── view/ Screens
|
|
||||||
│ ├── login/ Login-Flow
|
|
||||||
│ └── pages/ ein Verzeichnis pro Modul (timetable, files, talk, ...)
|
|
||||||
├── widget/ Geteilte UI-Komponenten (Dialoge, Buttons, Sheets)
|
|
||||||
├── extensions/ DateTime-, Text-, TimeOfDay-Extensions
|
|
||||||
├── routing/ AppRoutes (Single Navigation Entry)
|
|
||||||
├── theming/ Light/Dark Theme
|
|
||||||
├── storage/ Freezed Settings-Modelle (HydratedBloc-persistent)
|
|
||||||
├── notification/ Firebase + flutter_local_notifications
|
|
||||||
└── utils/ Helper (clipboard_helper, debouncer, download_manager, ...)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Konventionen
|
|
||||||
|
|
||||||
**Navigation:** Ausschließlich über `AppRoutes.openX(context, ...)`. Direkte `Navigator.push(...)` für volle Pages sind nicht erlaubt – `Navigator.pop` für Sheets/Dialogs bleibt am Call-Site.
|
|
||||||
|
|
||||||
**Dialoge:**
|
|
||||||
- Info/Fehler: `InfoDialog.show(context, body, copyable: true, title: '...')` aus `lib/widget/info_dialog.dart`.
|
|
||||||
- Bestätigung: `ConfirmDialog(...).asDialog(context)` aus `lib/widget/confirm_dialog.dart`. Async-Bestätigung nutzt `onConfirmAsync` (zeigt Spinner und Inline-Fehler über `AsyncDialogAction`).
|
|
||||||
- **Kein** inline `AlertDialog`/`SimpleDialog` mehr.
|
|
||||||
|
|
||||||
**Bottom-Sheets:** Detail-Sheets gehen über `showDetailsBottomSheet(context, header: ..., children: (ctx) => [...])` aus `lib/widget/details_bottom_sheet.dart`. Header ist optional.
|
|
||||||
|
|
||||||
**Async-Actions:** Statt manuelles Spinner+Try/Catch die `AsyncActionButton`-Familie aus `lib/widget/async_action_button.dart` (`AsyncActionButton`, `AsyncTextButton`, `AsyncIconButton`, `AsyncFab`, `AsyncListTile`, `AsyncDialogAction`, `runWithErrorDialog`). Fehler-Mapping läuft über `errorBuilder` oder zentral über `errorToUserMessage` aus `lib/api/errors/error_mapper.dart`.
|
|
||||||
|
|
||||||
**Clipboard:** Über `copyToClipboard(context, text)` aus `lib/utils/clipboard_helper.dart`. Zeigt automatisch SnackBar.
|
|
||||||
|
|
||||||
**Datum/Zeit-Formatierung:** Über die Extensions in `lib/extensions/date_time.dart`:
|
|
||||||
`dt.formatHm()`, `dt.formatDate()`, `dt.formatDateTime()`, `dt.formatDateShort()`, `dt.formatRelative()`, `start.timeRangeTo(end)`. **Kein** direktes `Jiffy.parseFromDateTime(...).format(pattern: '...')` im View-Code.
|
|
||||||
|
|
||||||
**Settings:** Pro Feature ein Freezed-Modell unter `lib/storage/`, persistiert via HydratedBloc.
|
|
||||||
|
|
||||||
**Session:** Die aktive Sitzung liegt in `SessionManager().current` (`lib/session/`). Nextcloud-Zugriffe nur über `SessionManager().requireNextcloud()`. Abmelden ausschließlich über `SessionLifecycle.signOut()`. Die Keychain-Keys in `SessionKeys` sind eingefroren (Bestandsinstallationen, iOS-NSE).
|
|
||||||
|
|
||||||
**Mehrere Konten:** Die `SessionKeys`-Slots, der MC-Token und die Group-Keychain spiegeln immer das *aktive* Konto; inaktive Konten liegen im Tresor (`accounts_index` + `account_vault_<id>`, `lib/session/account_codec.dart`). Wechseln/Hinzufügen/Entfernen nur über `SessionLifecycle` (`switchTo`, `beginAddAccount`/`finishLogin`/`cancelAddAccount`, `removeInactive`), danach `AccountBloc.activated(id)`. Lokale Daten sind pro Konto getrennt (`AccountStorage`: eigene HydratedBloc-Box; der Request-Cache `CacheStore` folgt dem aktiven Konto mit eigenem Verzeichnis); nur die Settings liegen in der globalen Box. `SessionManager().sessionEpoch` steigt bei jedem Kontowechsel – asynchrone Arbeit prüft damit, ob ihr Ergebnis noch zum aktiven Konto gehört. Was ein Konto außerhalb seines Speichers hinterlässt (Tray, Push-Schlüssel, Downloads), räumt `SessionWipe` auf. Alle Pro-Konto-Blocs gehören in `AccountScope` – er wird per Konto-ID neu aufgebaut (samt `MaterialApp`/Navigator). Push ist nur für das aktive Konto registriert.
|
|
||||||
|
|
||||||
## Build / Run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
flutter pub get
|
|
||||||
dart run build_runner build --delete-conflicting-outputs # nach Änderungen an Freezed/JSON-Modellen
|
|
||||||
flutter run # Debug auf angeschlossenem Device
|
|
||||||
flutter analyze # statische Analyse, muss 0 Issues melden
|
|
||||||
flutter test # Tests (siehe test/)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Backend-Integrationen
|
|
||||||
|
|
||||||
| Backend | Pfad | Zweck |
|
|
||||||
|---------------------------|-----------------------|----------------------------------------|
|
|
||||||
| MarianumConnect (Bearer) | `lib/api/marianumconnect/` | Auth, Stundenplan (Webuntis-Proxy), Ticker, Newsletter, Ferien, Abwesenheit, Capabilities, Push |
|
|
||||||
| Nextcloud (Talk + WebDAV) | `lib/api/marianumcloud/` | Chats, Datei-Verwaltung |
|
|
||||||
| MHSL (Legacy) | `lib/api/mhsl/` | nur noch Einmal-Migration der Custom Events |
|
|
||||||
|
|
||||||
`nextcloud`-Paket ist auf einen Custom-Fork gepinnt (siehe `pubspec.yaml` `dependency_overrides`).
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
|
|
||||||
`test/` deckt vor allem pure Funktionen ab (DateTime-Extensions, Stundenplan-Logik, Session-Codec). Beim Hinzufügen neuer pure-function-Helper bitte Test mit dazu.
|
|
||||||
@@ -1,91 +1,44 @@
|
|||||||
# Static analysis configuration for the Flutter project.
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# check for errors, warnings, and lints.
|
||||||
#
|
#
|
||||||
# Base ruleset: flutter_lints (recommended Flutter defaults).
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
# Additional lints below catch real bugs and enforce consistent style.
|
# 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
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
analyzer:
|
analyzer:
|
||||||
language:
|
|
||||||
strict-casts: true
|
|
||||||
strict-raw-types: true
|
|
||||||
errors:
|
errors:
|
||||||
invalid_annotation_target: ignore
|
invalid_annotation_target: ignore
|
||||||
todo: ignore
|
|
||||||
exclude:
|
|
||||||
- "**/*.g.dart"
|
|
||||||
- "**/*.freezed.dart"
|
|
||||||
- "lib/firebase_options.dart"
|
|
||||||
- "build/**"
|
|
||||||
- android/**
|
|
||||||
- ios/**
|
|
||||||
- web/**
|
|
||||||
|
|
||||||
linter:
|
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-lang.github.io/linter/lints/index.html.
|
||||||
|
#
|
||||||
|
# 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:
|
rules:
|
||||||
# === Project conventions ===
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
file_names: false
|
||||||
prefer_relative_imports: true
|
prefer_relative_imports: true
|
||||||
|
unnecessary_lambdas: true
|
||||||
prefer_single_quotes: true
|
prefer_single_quotes: true
|
||||||
eol_at_end_of_file: true
|
prefer_if_elements_to_conditional_expressions: true
|
||||||
|
prefer_expression_function_bodies: true
|
||||||
omit_local_variable_types: true
|
omit_local_variable_types: true
|
||||||
|
eol_at_end_of_file: true
|
||||||
|
cast_nullable_to_non_nullable: true
|
||||||
|
avoid_void_async: true
|
||||||
avoid_multiple_declarations_per_line: true
|
avoid_multiple_declarations_per_line: true
|
||||||
|
|
||||||
# === Bug catchers ===
|
# Additional information about this file can be found at
|
||||||
always_declare_return_types: true
|
# https://dart.dev/guides/language/analysis-options
|
||||||
avoid_empty_else: true
|
|
||||||
avoid_slow_async_io: true
|
|
||||||
avoid_type_to_string: true
|
|
||||||
avoid_void_async: true
|
|
||||||
await_only_futures: true
|
|
||||||
cancel_subscriptions: true
|
|
||||||
cast_nullable_to_non_nullable: true
|
|
||||||
close_sinks: true
|
|
||||||
empty_catches: true
|
|
||||||
hash_and_equals: true
|
|
||||||
no_adjacent_strings_in_list: true
|
|
||||||
no_duplicate_case_values: true
|
|
||||||
test_types_in_equals: true
|
|
||||||
throw_in_finally: true
|
|
||||||
unawaited_futures: true
|
|
||||||
unnecessary_statements: true
|
|
||||||
unrelated_type_equality_checks: true
|
|
||||||
use_build_context_synchronously: true
|
|
||||||
valid_regexps: true
|
|
||||||
|
|
||||||
# === Flutter widget hygiene ===
|
|
||||||
avoid_unnecessary_containers: true
|
|
||||||
sized_box_for_whitespace: true
|
|
||||||
sort_child_properties_last: true
|
|
||||||
use_colored_box: true
|
|
||||||
use_decorated_box: true
|
|
||||||
use_full_hex_values_for_flutter_colors: true
|
|
||||||
use_key_in_widget_constructors: true
|
|
||||||
|
|
||||||
# === Code clarity ===
|
|
||||||
directives_ordering: true
|
|
||||||
library_prefixes: true
|
|
||||||
no_leading_underscores_for_local_identifiers: true
|
|
||||||
prefer_conditional_assignment: true
|
|
||||||
prefer_if_elements_to_conditional_expressions: true
|
|
||||||
prefer_if_null_operators: true
|
|
||||||
prefer_initializing_formals: true
|
|
||||||
prefer_interpolation_to_compose_strings: true
|
|
||||||
prefer_is_empty: true
|
|
||||||
prefer_is_not_empty: true
|
|
||||||
prefer_is_not_operator: true
|
|
||||||
prefer_iterable_whereType: true
|
|
||||||
prefer_null_aware_operators: true
|
|
||||||
prefer_spread_collections: true
|
|
||||||
prefer_void_to_null: true
|
|
||||||
unnecessary_await_in_return: true
|
|
||||||
unnecessary_brace_in_string_interps: true
|
|
||||||
unnecessary_lambdas: true
|
|
||||||
unnecessary_null_aware_assignments: true
|
|
||||||
unnecessary_null_checks: true
|
|
||||||
unnecessary_parenthesis: true
|
|
||||||
unnecessary_string_interpolations: true
|
|
||||||
use_super_parameters: true
|
|
||||||
|
|
||||||
# === File naming ===
|
|
||||||
file_names: true
|
|
||||||
@@ -11,4 +11,3 @@ GeneratedPluginRegistrant.java
|
|||||||
key.properties
|
key.properties
|
||||||
**/*.keystore
|
**/*.keystore
|
||||||
**/*.jks
|
**/*.jks
|
||||||
.kotlin/
|
|
||||||
@@ -25,7 +25,7 @@ if (flutterVersionName == null) {
|
|||||||
android {
|
android {
|
||||||
namespace "eu.mhsl.marianum.mobile.client"
|
namespace "eu.mhsl.marianum.mobile.client"
|
||||||
compileSdk flutter.compileSdkVersion
|
compileSdk flutter.compileSdkVersion
|
||||||
ndkVersion "28.2.13676358"
|
ndkVersion "27.0.12077973"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_17
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
@@ -33,6 +33,10 @@ android {
|
|||||||
coreLibraryDesugaringEnabled true
|
coreLibraryDesugaringEnabled true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '17'
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main.java.srcDirs += 'src/main/kotlin'
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
}
|
}
|
||||||
@@ -43,6 +47,7 @@ android {
|
|||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
multiDexEnabled true
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -52,11 +57,8 @@ android {
|
|||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
buildFeatures {
|
||||||
|
viewBinding true
|
||||||
kotlin {
|
|
||||||
compilerOptions {
|
|
||||||
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,9 +67,6 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Same version as workmanager_android pins — needed to enqueue its
|
implementation 'com.android.support:multidex:2.0.1'
|
||||||
// BackgroundWorker from native widget code (the plugin uses
|
|
||||||
// `implementation`, so androidx.work is not exposed transitively).
|
|
||||||
implementation 'androidx.work:work-runtime:2.11.2'
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,4 @@
|
|||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
||||||
<!-- Allow cleartext HTTP in debug builds so developers can point the
|
|
||||||
Marianum-Connect custom endpoint at a local backend (e.g.
|
|
||||||
http://10.0.2.2:8080 from the Android emulator). Release builds
|
|
||||||
keep the default cleartext block. -->
|
|
||||||
<application android:usesCleartextTraffic="true" />
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,156 +1,73 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
<manifest
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Required to query activities that can process text, see:
|
||||||
|
https://developer.android.com/training/package-visibility?hl=en and
|
||||||
|
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||||
|
|
||||||
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin.
|
||||||
|
-->
|
||||||
|
<queries>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.PROCESS_TEXT" />
|
||||||
|
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent>
|
||||||
|
</queries>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="Marianum Fulda"
|
tools:replace="android:label"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:label="Marianum Fulda">
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules">
|
<receiver
|
||||||
|
android:name=".TimetableWidget"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/timetable_widget_info" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:theme="@style/LaunchTheme"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:exported="true"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/LaunchTheme"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
|
||||||
|
<!--
|
||||||
|
Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI.
|
||||||
|
-->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme" />
|
||||||
/>
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
<data android:mimeType="video/*" />
|
|
||||||
<data android:mimeType="application/*" />
|
|
||||||
<data android:mimeType="text/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
<data android:mimeType="video/*" />
|
|
||||||
<data android:mimeType="application/*" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!--
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
Don't delete the meta-data below.
|
||||||
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java
|
||||||
|
-->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
||||||
<!-- Fallback small icon + accent for anything FCM ever renders itself
|
|
||||||
(e.g. plain notification messages). Launcher mipmaps are unusable
|
|
||||||
as small icons: Android only draws their alpha silhouette, which
|
|
||||||
shows up as a solid circle in the status bar. -->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
|
||||||
android:resource="@drawable/ic_stat_notification" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.firebase.messaging.default_notification_color"
|
|
||||||
android:resource="@color/notification_accent" />
|
|
||||||
|
|
||||||
<!-- flutter_local_notifications liefert Notification-Action-Taps (Talk:
|
|
||||||
Antworten / Gelesen) als expliziten Broadcast an diesen Receiver.
|
|
||||||
Das Plugin deklariert ihn NICHT selbst — ohne diesen Eintrag kommt
|
|
||||||
der Tap nirgends an und der Background-Handler startet nie. -->
|
|
||||||
<receiver
|
|
||||||
android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver"
|
|
||||||
android:exported="false" />
|
|
||||||
|
|
||||||
<!-- background_downloader runs large/long downloads in a foreground
|
|
||||||
service (WorkManager) so they survive the app being backgrounded and
|
|
||||||
beat the default 9-minute WorkManager timeout. On API 34+ the
|
|
||||||
dataSync foreground service type must be declared explicitly here;
|
|
||||||
see the FOREGROUND_SERVICE_DATA_SYNC permission below. -->
|
|
||||||
<service
|
|
||||||
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
|
||||||
android:foregroundServiceType="dataSync"
|
|
||||||
tools:node="merge" />
|
|
||||||
|
|
||||||
<!-- Receiver classes live at the package root (NOT under .widgets) because
|
|
||||||
the home_widget Flutter plugin resolves them as <app-package>.<name>. -->
|
|
||||||
<receiver
|
|
||||||
android:name="eu.mhsl.marianum.mobile.client.TimetableDayWidget"
|
|
||||||
android:enabled="@bool/widget_supported"
|
|
||||||
android:label="@string/widget_day_label"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
|
||||||
</intent-filter>
|
|
||||||
<meta-data
|
|
||||||
android:name="android.appwidget.provider"
|
|
||||||
android:resource="@xml/timetable_day_widget_info" />
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name="eu.mhsl.marianum.mobile.client.TimetableWeekWidget"
|
|
||||||
android:enabled="@bool/widget_supported"
|
|
||||||
android:label="@string/widget_week_label"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
|
||||||
</intent-filter>
|
|
||||||
<meta-data
|
|
||||||
android:name="android.appwidget.provider"
|
|
||||||
android:resource="@xml/timetable_week_widget_info" />
|
|
||||||
</receiver>
|
|
||||||
</application>
|
</application>
|
||||||
<!-- Required so url_launcher / can_launch can actually see browsers,
|
|
||||||
mail clients and dialers under Android 11+ package-visibility rules
|
|
||||||
(otherwise UrlLauncher logs "component name for ... is null" and
|
|
||||||
link taps in Talk silently do nothing). The PROCESS_TEXT intent is
|
|
||||||
needed by io.flutter.plugin.text.ProcessTextPlugin (selection
|
|
||||||
menu).
|
|
||||||
See https://developer.android.com/training/package-visibility -->
|
|
||||||
<queries>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
|
||||||
<data android:mimeType="text/plain"/>
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
<data android:scheme="https"/>
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
<data android:scheme="http"/>
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
<data android:scheme="mailto"/>
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
<data android:scheme="tel"/>
|
|
||||||
</intent>
|
|
||||||
</queries>
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
<!-- Android 13+ runtime notification permission. Requested at login via
|
|
||||||
FirebaseMessaging.requestPermission(); without this declaration the
|
|
||||||
locally rendered push notifications are silently dropped. -->
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
|
||||||
<!-- background_downloader foreground service for large/long downloads that
|
|
||||||
must keep running while the app is backgrounded. DATA_SYNC is the
|
|
||||||
required type declaration on Android 14+ (API 34+). -->
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
|
|
||||||
<!-- Workmanager periodic widget refresh needs to reschedule after device
|
|
||||||
reboot, otherwise the widget freezes until the user opens the app. -->
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
||||||
<!-- Aus open_filex gemergt: die App öffnet nur selbst heruntergeladene Dateien
|
|
||||||
über dessen FileProvider (content://-URIs) und braucht keinen Zugriff auf
|
|
||||||
geteilte Medien. Entfernt wegen Google-Play "Photo and Video Permissions". -->
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" tools:node="remove"/>
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" tools:node="remove"/>
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" tools:node="remove"/>
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package eu.mhsl.marianum.mobile.client
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.appwidget.AppWidgetProvider
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.widget.RemoteViews
|
||||||
|
|
||||||
|
import es.antonborri.home_widget.HomeWidgetPlugin
|
||||||
|
import android.util.Base64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of App Widget functionality.
|
||||||
|
*/
|
||||||
|
class TimetableWidget : AppWidgetProvider() {
|
||||||
|
override fun onUpdate(
|
||||||
|
context: Context,
|
||||||
|
appWidgetManager: AppWidgetManager,
|
||||||
|
appWidgetIds: IntArray,
|
||||||
|
) {
|
||||||
|
for (appWidgetId in appWidgetIds) {
|
||||||
|
val widgetData = HomeWidgetPlugin.getData(context)
|
||||||
|
val views = RemoteViews(context.packageName, R.layout.timetable_widget).apply {
|
||||||
|
val imageBase64 = widgetData.getString("screen", null) ?: return@apply
|
||||||
|
val imageBytes = Base64.decode(imageBase64, Base64.DEFAULT);
|
||||||
|
val imageBitmap: Bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
|
||||||
|
setImageViewBitmap(R.id.widget_image, imageBitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
|
||||||
|
val pendingIntent = PendingIntent.getActivity(context, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||||
|
views.setOnClickPendingIntent(R.id.background, pendingIntent)
|
||||||
|
|
||||||
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// Generated file.
|
||||||
|
//
|
||||||
|
// If you wish to remove Flutter's multidex support, delete this entire file.
|
||||||
|
//
|
||||||
|
// Modifications to this file should be done in a copy under a different name
|
||||||
|
// as this file may be regenerated.
|
||||||
|
|
||||||
|
package io.flutter.app;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.annotation.CallSuper;
|
||||||
|
import androidx.multidex.MultiDex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link android.app.Application}, adding multidex support.
|
||||||
|
*/
|
||||||
|
public class FlutterMultiDexApplication extends Application {
|
||||||
|
@Override
|
||||||
|
@CallSuper
|
||||||
|
protected void attachBaseContext(Context base) {
|
||||||
|
super.attachBaseContext(base);
|
||||||
|
MultiDex.install(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +1,5 @@
|
|||||||
package eu.mhsl.marianum.mobile.client
|
package eu.mhsl.marianum.mobile.client
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
import io.flutter.embedding.engine.FlutterEngine
|
|
||||||
import io.flutter.plugin.common.MethodChannel
|
|
||||||
|
|
||||||
class MainActivity : FlutterActivity() {
|
class MainActivity: FlutterActivity()
|
||||||
private val widgetChannel = "eu.mhsl.marianum.widget"
|
|
||||||
private val shareChannel = "eu.mhsl.marianum.share"
|
|
||||||
/// Last seen widget tap target. Cleared by Dart via `consumePendingNavigation`
|
|
||||||
/// so the same intent isn't replayed on every resume.
|
|
||||||
private var pendingTimetableTap: Boolean = false
|
|
||||||
private val shareActions = setOf(Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE)
|
|
||||||
|
|
||||||
/// receive_sharing_intent only emits warm shares to a live Dart listener and
|
|
||||||
/// does not buffer them. After a relaunch into an existing task the share
|
|
||||||
/// arrives via onNewIntent before Dart subscribed, so it is held here until
|
|
||||||
/// Dart reports `listenerReady`.
|
|
||||||
private var shareListenerReady = false
|
|
||||||
private var bufferedShare: Intent? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
// Android replays the original launch intent when the activity is
|
|
||||||
// recreated from recents or after process death. A share or widget tap
|
|
||||||
// that was already handled would otherwise run again — for shares with
|
|
||||||
// temp files that are long gone.
|
|
||||||
val replayed = savedInstanceState != null ||
|
|
||||||
(intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0
|
|
||||||
if (replayed && (intent.action in shareActions || isWidgetTap(intent))) {
|
|
||||||
intent = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER)
|
|
||||||
}
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
|
||||||
super.configureFlutterEngine(flutterEngine)
|
|
||||||
MethodChannel(
|
|
||||||
flutterEngine.dartExecutor.binaryMessenger,
|
|
||||||
widgetChannel
|
|
||||||
).setMethodCallHandler { call, result ->
|
|
||||||
when (call.method) {
|
|
||||||
"consumePendingNavigation" -> {
|
|
||||||
val pending = pendingTimetableTap
|
|
||||||
pendingTimetableTap = false
|
|
||||||
result.success(pending)
|
|
||||||
}
|
|
||||||
else -> result.notImplemented()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MethodChannel(
|
|
||||||
flutterEngine.dartExecutor.binaryMessenger,
|
|
||||||
shareChannel
|
|
||||||
).setMethodCallHandler { call, result ->
|
|
||||||
when (call.method) {
|
|
||||||
"listenerReady" -> {
|
|
||||||
shareListenerReady = true
|
|
||||||
bufferedShare?.let { flutterEngine.activityControlSurface.onNewIntent(it) }
|
|
||||||
bufferedShare = null
|
|
||||||
result.success(null)
|
|
||||||
}
|
|
||||||
else -> result.notImplemented()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
consumeIntentData(intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
|
||||||
super.onNewIntent(intent)
|
|
||||||
if (!shareListenerReady && intent.action in shareActions) {
|
|
||||||
bufferedShare = intent
|
|
||||||
}
|
|
||||||
consumeIntentData(intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isWidgetTap(intent: Intent?): Boolean =
|
|
||||||
intent?.getBooleanExtra("widget_open_timetable", false) == true
|
|
||||||
|
|
||||||
private fun consumeIntentData(intent: Intent?) {
|
|
||||||
if (isWidgetTap(intent)) pendingTimetableTap = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package eu.mhsl.marianum.mobile.client
|
|
||||||
|
|
||||||
import android.appwidget.AppWidgetManager
|
|
||||||
import android.appwidget.AppWidgetProvider
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import eu.mhsl.marianum.mobile.client.widgets.WidgetRefreshRequester
|
|
||||||
import eu.mhsl.marianum.mobile.client.widgets.WidgetRenderer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lives at the package root (not under `widgets/`) because the home_widget
|
|
||||||
* Flutter plugin resolves the receiver class as `<app-package>.<androidName>`.
|
|
||||||
*/
|
|
||||||
class TimetableDayWidget : AppWidgetProvider() {
|
|
||||||
override fun onEnabled(context: Context) {
|
|
||||||
// First widget of this kind placed → fetch fresh data right away.
|
|
||||||
WidgetRefreshRequester.enqueueOneOffRefresh(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUpdate(
|
|
||||||
context: Context,
|
|
||||||
appWidgetManager: AppWidgetManager,
|
|
||||||
appWidgetIds: IntArray,
|
|
||||||
) {
|
|
||||||
for (id in appWidgetIds) {
|
|
||||||
val options = appWidgetManager.getAppWidgetOptions(id)
|
|
||||||
val views = WidgetRenderer.buildDay(context, context.packageName, options)
|
|
||||||
appWidgetManager.updateAppWidget(id, views)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAppWidgetOptionsChanged(
|
|
||||||
context: Context,
|
|
||||||
appWidgetManager: AppWidgetManager,
|
|
||||||
appWidgetId: Int,
|
|
||||||
newOptions: Bundle,
|
|
||||||
) {
|
|
||||||
// Re-render on resize, otherwise the tiles stay at install-time size
|
|
||||||
// and either clip or leave dead space.
|
|
||||||
val views = WidgetRenderer.buildDay(context, context.packageName, newOptions)
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package eu.mhsl.marianum.mobile.client
|
|
||||||
|
|
||||||
import android.appwidget.AppWidgetManager
|
|
||||||
import android.appwidget.AppWidgetProvider
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import eu.mhsl.marianum.mobile.client.widgets.WidgetRefreshRequester
|
|
||||||
import eu.mhsl.marianum.mobile.client.widgets.WidgetRenderer
|
|
||||||
|
|
||||||
class TimetableWeekWidget : AppWidgetProvider() {
|
|
||||||
override fun onEnabled(context: Context) {
|
|
||||||
// First widget of this kind placed → fetch fresh data right away.
|
|
||||||
WidgetRefreshRequester.enqueueOneOffRefresh(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUpdate(
|
|
||||||
context: Context,
|
|
||||||
appWidgetManager: AppWidgetManager,
|
|
||||||
appWidgetIds: IntArray,
|
|
||||||
) {
|
|
||||||
for (id in appWidgetIds) {
|
|
||||||
val options = appWidgetManager.getAppWidgetOptions(id)
|
|
||||||
val views = WidgetRenderer.buildWeek(context, context.packageName, options)
|
|
||||||
appWidgetManager.updateAppWidget(id, views)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAppWidgetOptionsChanged(
|
|
||||||
context: Context,
|
|
||||||
appWidgetManager: AppWidgetManager,
|
|
||||||
appWidgetId: Int,
|
|
||||||
newOptions: Bundle,
|
|
||||||
) {
|
|
||||||
val views = WidgetRenderer.buildWeek(context, context.packageName, newOptions)
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
package eu.mhsl.marianum.mobile.client.widgets
|
|
||||||
|
|
||||||
import org.json.JSONException
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Calendar
|
|
||||||
import java.util.Date
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.TimeZone
|
|
||||||
|
|
||||||
// Mirror of lib/widget_data/widget_data.dart — JSON keys + enum names
|
|
||||||
// must stay in sync.
|
|
||||||
enum class WidgetLessonStatus {
|
|
||||||
REGULAR, ONGOING, PAST, CANCELLED, IRREGULAR, TEACHER_CHANGED, EVENT, DUTY;
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun fromWire(raw: String?): WidgetLessonStatus = when (raw) {
|
|
||||||
"regular" -> REGULAR
|
|
||||||
"ongoing" -> ONGOING
|
|
||||||
"past" -> PAST
|
|
||||||
"cancelled" -> CANCELLED
|
|
||||||
"irregular" -> IRREGULAR
|
|
||||||
"teacherChanged" -> TEACHER_CHANGED
|
|
||||||
"event" -> EVENT
|
|
||||||
"duty" -> DUTY
|
|
||||||
else -> REGULAR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class WidgetLesson(
|
|
||||||
val start: Date,
|
|
||||||
val end: Date,
|
|
||||||
val subjectShort: String,
|
|
||||||
val subjectLong: String?,
|
|
||||||
val room: String?,
|
|
||||||
// On teacher accounts this carries the class label ("7a") instead of the
|
|
||||||
// teacher short name (originalTeacher is null then) — mapped in Dart.
|
|
||||||
val teacher: String?,
|
|
||||||
val originalTeacher: String?,
|
|
||||||
val status: WidgetLessonStatus,
|
|
||||||
val customColor: String?,
|
|
||||||
// Tile colour resolved in Dart (subject colours, palettes); null only for
|
|
||||||
// payloads written before the field existed.
|
|
||||||
val color: Int?,
|
|
||||||
val siblingCount: Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class WidgetPeriod(
|
|
||||||
val name: String,
|
|
||||||
val startMinutes: Int,
|
|
||||||
val endMinutes: Int,
|
|
||||||
val virtualStartMinutes: Int,
|
|
||||||
val virtualEndMinutes: Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class WidgetDayInfo(
|
|
||||||
val date: Date,
|
|
||||||
val isHoliday: Boolean,
|
|
||||||
val holidayName: String?,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class WidgetTimetableData(
|
|
||||||
val fetchedAt: Date,
|
|
||||||
val anchorDate: Date,
|
|
||||||
val lessons: List<WidgetLesson>,
|
|
||||||
val periods: List<WidgetPeriod>,
|
|
||||||
val isHoliday: Boolean,
|
|
||||||
val holidayName: String?,
|
|
||||||
// Week payload only; empty for the day payload.
|
|
||||||
val days: List<WidgetDayInfo>,
|
|
||||||
)
|
|
||||||
|
|
||||||
object WidgetDataParser {
|
|
||||||
private val isoFormat: SimpleDateFormat
|
|
||||||
get() = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ROOT).apply {
|
|
||||||
timeZone = TimeZone.getDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dart's toIso8601String() ships microseconds (6 digits) when non-zero;
|
|
||||||
/// SimpleDateFormat only parses 3 → strip the extra digits. Local time
|
|
||||||
/// without Z is the default, so removeSuffix("Z") makes the parser
|
|
||||||
/// tolerate both shapes.
|
|
||||||
private fun parseDate(raw: String?): Date? {
|
|
||||||
if (raw.isNullOrEmpty()) return null
|
|
||||||
val cleaned = raw
|
|
||||||
.replace(Regex("([.,]\\d{3})\\d+"), "$1")
|
|
||||||
.removeSuffix("Z")
|
|
||||||
return try {
|
|
||||||
isoFormat.parse(cleaned)
|
|
||||||
} catch (_: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseColor(raw: String?): Int? {
|
|
||||||
if (raw == null || !Regex("#[0-9A-Fa-f]{6}").matches(raw)) return null
|
|
||||||
return 0xFF000000.toInt() or raw.substring(1).toInt(16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parse(json: String?): WidgetTimetableData? {
|
|
||||||
if (json.isNullOrEmpty()) return null
|
|
||||||
return try {
|
|
||||||
val root = JSONObject(json)
|
|
||||||
val lessonsArray = root.optJSONArray("lessons")
|
|
||||||
val lessons = mutableListOf<WidgetLesson>()
|
|
||||||
if (lessonsArray != null) {
|
|
||||||
for (i in 0 until lessonsArray.length()) {
|
|
||||||
val obj = lessonsArray.optJSONObject(i) ?: continue
|
|
||||||
val start = parseDate(obj.stringOrNull("start")) ?: continue
|
|
||||||
val end = parseDate(obj.stringOrNull("end")) ?: continue
|
|
||||||
lessons += WidgetLesson(
|
|
||||||
start = start,
|
|
||||||
end = end,
|
|
||||||
subjectShort = obj.stringOrNull("subjectShort") ?: "",
|
|
||||||
subjectLong = obj.stringOrNull("subjectLong"),
|
|
||||||
room = obj.stringOrNull("room"),
|
|
||||||
teacher = obj.stringOrNull("teacher"),
|
|
||||||
originalTeacher = obj.stringOrNull("originalTeacher"),
|
|
||||||
status = WidgetLessonStatus.fromWire(obj.stringOrNull("status")),
|
|
||||||
customColor = obj.stringOrNull("customColor"),
|
|
||||||
color = parseColor(obj.stringOrNull("color")),
|
|
||||||
siblingCount = obj.optInt("siblingCount", 0),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val periodsArray = root.optJSONArray("periods")
|
|
||||||
val periods = mutableListOf<WidgetPeriod>()
|
|
||||||
if (periodsArray != null) {
|
|
||||||
for (i in 0 until periodsArray.length()) {
|
|
||||||
val obj = periodsArray.optJSONObject(i) ?: continue
|
|
||||||
periods += WidgetPeriod(
|
|
||||||
name = obj.stringOrNull("name") ?: "",
|
|
||||||
startMinutes = obj.optInt("startMinutes", 0),
|
|
||||||
endMinutes = obj.optInt("endMinutes", 0),
|
|
||||||
virtualStartMinutes = obj.optInt("virtualStartMinutes", 0),
|
|
||||||
virtualEndMinutes = obj.optInt("virtualEndMinutes", 0),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val daysArray = root.optJSONArray("days")
|
|
||||||
val days = mutableListOf<WidgetDayInfo>()
|
|
||||||
if (daysArray != null) {
|
|
||||||
for (i in 0 until daysArray.length()) {
|
|
||||||
val obj = daysArray.optJSONObject(i) ?: continue
|
|
||||||
days += WidgetDayInfo(
|
|
||||||
date = parseDate(obj.stringOrNull("date")) ?: continue,
|
|
||||||
isHoliday = obj.optBoolean("isHoliday", false),
|
|
||||||
holidayName = obj.stringOrNull("holidayName"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WidgetTimetableData(
|
|
||||||
fetchedAt = parseDate(root.stringOrNull("fetchedAt")) ?: Date(),
|
|
||||||
anchorDate = parseDate(root.stringOrNull("anchorDate")) ?: Date(),
|
|
||||||
lessons = lessons,
|
|
||||||
periods = periods,
|
|
||||||
isHoliday = root.optBoolean("isHoliday", false),
|
|
||||||
holidayName = root.stringOrNull("holidayName"),
|
|
||||||
days = days,
|
|
||||||
)
|
|
||||||
} catch (_: JSONException) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun JSONObject.stringOrNull(key: String): String? {
|
|
||||||
if (!has(key) || isNull(key)) return null
|
|
||||||
val raw = optString(key, "")
|
|
||||||
return if (raw.isEmpty()) null else raw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object WidgetDateUtils {
|
|
||||||
fun startOfDay(date: Date): Date {
|
|
||||||
val cal = Calendar.getInstance().apply { time = date }
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 0)
|
|
||||||
cal.set(Calendar.MINUTE, 0)
|
|
||||||
cal.set(Calendar.SECOND, 0)
|
|
||||||
cal.set(Calendar.MILLISECOND, 0)
|
|
||||||
return cal.time
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isSameDay(a: Date, b: Date): Boolean {
|
|
||||||
val ca = Calendar.getInstance().apply { time = a }
|
|
||||||
val cb = Calendar.getInstance().apply { time = b }
|
|
||||||
return ca.get(Calendar.YEAR) == cb.get(Calendar.YEAR) &&
|
|
||||||
ca.get(Calendar.DAY_OF_YEAR) == cb.get(Calendar.DAY_OF_YEAR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package eu.mhsl.marianum.mobile.client.widgets
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.work.Constraints
|
|
||||||
import androidx.work.Data
|
|
||||||
import androidx.work.NetworkType
|
|
||||||
import androidx.work.OneTimeWorkRequest
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import dev.fluttercommunity.workmanager.BackgroundWorker
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enqueues the app's Dart one-off widget refresh from native code, so a
|
|
||||||
* freshly placed widget populates within seconds instead of waiting for the
|
|
||||||
* next periodic slot.
|
|
||||||
*
|
|
||||||
* DART_TASK_KEY is public plugin API but no semver guarantee — re-verify on
|
|
||||||
* workmanager upgrades. The Dart callback handle comes from SharedPreferences
|
|
||||||
* persisted by Workmanager().initialize(); if the app never ran, the worker
|
|
||||||
* fails gracefully and the widget keeps rendering its cached/empty state.
|
|
||||||
*/
|
|
||||||
object WidgetRefreshRequester {
|
|
||||||
// Mirrors WidgetBackgroundTask.oneOffTaskName on the Dart side.
|
|
||||||
private const val DART_ONE_OFF_TASK = "eu.mhsl.marianum.widget.refresh.once"
|
|
||||||
|
|
||||||
fun enqueueOneOffRefresh(context: Context) {
|
|
||||||
val request = OneTimeWorkRequest.Builder(BackgroundWorker::class.java)
|
|
||||||
.setInputData(
|
|
||||||
Data.Builder()
|
|
||||||
.putString(BackgroundWorker.DART_TASK_KEY, DART_ONE_OFF_TASK)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.setConstraints(
|
|
||||||
Constraints.Builder()
|
|
||||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
WorkManager.getInstance(context).enqueue(request)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 454 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 319 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Background for widgets to make the rounded corners based on the
|
||||||
|
appWidgetRadius attribute value
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<corners android:radius="?attr/appWidgetRadius" />
|
||||||
|
<solid android:color="?android:attr/colorBackground" />
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Background for views inside widgets to make the rounded corners based on the
|
||||||
|
appWidgetInnerRadius attribute value
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<corners android:radius="?attr/appWidgetInnerRadius" />
|
||||||
|
<solid android:color="?android:attr/colorAccent" />
|
||||||
|
</shape>
|
||||||
|
Before Width: | Height: | Size: 69 B After Width: | Height: | Size: 69 B |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 654 B After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 1021 B After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 21 KiB |
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Plain rounded rectangle. We deliberately avoid ?attr/appWidgetRadius
|
|
||||||
because RemoteViews inflation does not resolve custom theme attributes
|
|
||||||
reliably across launchers. Hard-coded 20dp matches the system home-screen
|
|
||||||
radius closely on stock Android. -->
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<corners android:radius="20dp" />
|
|
||||||
<solid android:color="@color/widget_background" />
|
|
||||||
</shape>
|
|
||||||
|
Before Width: | Height: | Size: 69 B After Width: | Height: | Size: 69 B |
@@ -1,34 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Status-bar small icon: monochrome Marianum M, ported from
|
|
||||||
marianum_m_watermark.xml (same path + nested transforms). Android renders
|
|
||||||
only the alpha channel of small icons, so the fill is hard white and never
|
|
||||||
tinted at runtime. 24dp with the source's non-square viewport — the system
|
|
||||||
fits it into the icon bounds.
|
|
||||||
-->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="70.000168"
|
|
||||||
android:viewportHeight="82.227348">
|
|
||||||
|
|
||||||
<group
|
|
||||||
android:scaleX="0.26458333"
|
|
||||||
android:scaleY="0.26458334"
|
|
||||||
android:translateX="107.44411"
|
|
||||||
android:translateY="-80.482198">
|
|
||||||
<group
|
|
||||||
android:translateX="-749.41293"
|
|
||||||
android:translateY="290.52252">
|
|
||||||
<group
|
|
||||||
android:scaleX="0.13333333"
|
|
||||||
android:scaleY="-0.13333333"
|
|
||||||
android:translateX="0"
|
|
||||||
android:translateY="632.14667">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M 3499.67,4594.33 c -16.43,-106.19 -29.71,-199.97 -43.79,-293.49 86.83,-19 138.5,-27.61 223.38,-43.82 63.81,-12.18 175.24,-20.4 179.64,-83.23 6.46,-92.69 -124.69,-55.41 -188.38,-43.81 -84.33,15.36 -159.13,28.84 -232.2,43.81 -13.68,-60.72 -26.83,-118.68 -39.43,-179.61 -36.76,-178.32 -73.67,-368.16 -105.11,-551.97 18.09,25.66 30.84,42.72 43.8,65.7 66.7,118.26 140.39,245.04 227.76,354.83 33.49,42.05 76.86,94.81 118.31,113.91 98.42,45.36 166.68,-22.2 170.87,-118.28 3.68,-85.28 -23.09,-181.17 -35.08,-275.99 -12.4,-98.19 -22.89,-194.93 -35.03,-275.98 72.44,102.69 147.93,269.64 240.95,381.12 27.51,33 73.55,80.61 118.27,87.62 218.76,34.33 126.58,-312.17 127.05,-473.13 0.4,-144.9 44.01,-255.37 175.21,-271.59 43.02,-5.31 105.84,11.16 112.7,-26.34 8.67,-47.38 -78.15,-60.52 -125.84,-61.28 -291.34,-4.51 -322.06,262.33 -311.01,573.88 -19.85,-18.57 -35.71,-47.53 -52.57,-74.47 -97.59,-155.88 -203.95,-327.22 -297.92,-503.79 -25.93,-48.79 -53.68,-114.7 -135.8,-83.23 -17.27,6.63 -48.25,44.39 -52.56,56.96 -19.58,57.19 1.55,137.42 8.76,205.89 21.54,203.72 57.81,389.09 78.87,587.01 -26.3,0.51 -43.93,-30.07 -56.96,-48.2 -46.9,-65.27 -86.02,-140.76 -127.04,-214.64 -52.84,-95.15 -108.23,-192.84 -157.71,-293.52 -75.25,-153.09 -188.6,-501.89 -242.12,-678.81 -8.67,-28.67 -17.7,-58.08 -26.3,-87.64 -7.48,-25.72 -10.39,-57.68 -35.05,-74.46 -100.02,18.93 -89.71,104.89 -70.09,205.9 47.35,243.43 170.89,706.45 211.48,946.04 -72.97,-70.97 -153.99,-207.41 -289.14,-236.55 -136.47,-29.44 -217.95,47.68 -271.6,122.66 -17.14,23.96 -41.43,49.54 -26.29,78.84 83.96,35.51 113.37,-65.2 197.15,-74.47 22.65,-2.5 54.56,2.4 74.46,8.78 132.4,42.34 237.57,218.76 297.87,346.07 74.16,156.45 125.32,330.5 148.95,490.64 -65.71,11.4 -142.96,22.15 -219.25,36.52 -109.8,20.72 -158.81,10.75 -201.29,59.86 9.15,41.95 41.41,60.8 70.1,83.24 126.26,-16.84 252.45,-33.77 372.36,-56.97 20.43,89.25 51.98,218.51 74.45,311.05 40.53,26.02 88.88,-8.43 105.17,-35.06 z" />
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Direct port of /home/elias/Bilder/marianum_m_white.svg.
|
|
||||||
- viewport matches the source SVG (70mm × 82.2mm).
|
|
||||||
- Transforms recreate the SVG's three nested matrices: outer scale+offset,
|
|
||||||
inner translate, and a final scale+y-flip that pulls the path data into
|
|
||||||
the visible coordinate space.
|
|
||||||
- Tinted at runtime via setColorFilter so light/dark themes can share one
|
|
||||||
drawable.
|
|
||||||
-->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="70dp"
|
|
||||||
android:height="82dp"
|
|
||||||
android:viewportWidth="70.000168"
|
|
||||||
android:viewportHeight="82.227348">
|
|
||||||
|
|
||||||
<group
|
|
||||||
android:scaleX="0.26458333"
|
|
||||||
android:scaleY="0.26458334"
|
|
||||||
android:translateX="107.44411"
|
|
||||||
android:translateY="-80.482198">
|
|
||||||
<group
|
|
||||||
android:translateX="-749.41293"
|
|
||||||
android:translateY="290.52252">
|
|
||||||
<group
|
|
||||||
android:scaleX="0.13333333"
|
|
||||||
android:scaleY="-0.13333333"
|
|
||||||
android:translateX="0"
|
|
||||||
android:translateY="632.14667">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M 3499.67,4594.33 c -16.43,-106.19 -29.71,-199.97 -43.79,-293.49 86.83,-19 138.5,-27.61 223.38,-43.82 63.81,-12.18 175.24,-20.4 179.64,-83.23 6.46,-92.69 -124.69,-55.41 -188.38,-43.81 -84.33,15.36 -159.13,28.84 -232.2,43.81 -13.68,-60.72 -26.83,-118.68 -39.43,-179.61 -36.76,-178.32 -73.67,-368.16 -105.11,-551.97 18.09,25.66 30.84,42.72 43.8,65.7 66.7,118.26 140.39,245.04 227.76,354.83 33.49,42.05 76.86,94.81 118.31,113.91 98.42,45.36 166.68,-22.2 170.87,-118.28 3.68,-85.28 -23.09,-181.17 -35.08,-275.99 -12.4,-98.19 -22.89,-194.93 -35.03,-275.98 72.44,102.69 147.93,269.64 240.95,381.12 27.51,33 73.55,80.61 118.27,87.62 218.76,34.33 126.58,-312.17 127.05,-473.13 0.4,-144.9 44.01,-255.37 175.21,-271.59 43.02,-5.31 105.84,11.16 112.7,-26.34 8.67,-47.38 -78.15,-60.52 -125.84,-61.28 -291.34,-4.51 -322.06,262.33 -311.01,573.88 -19.85,-18.57 -35.71,-47.53 -52.57,-74.47 -97.59,-155.88 -203.95,-327.22 -297.92,-503.79 -25.93,-48.79 -53.68,-114.7 -135.8,-83.23 -17.27,6.63 -48.25,44.39 -52.56,56.96 -19.58,57.19 1.55,137.42 8.76,205.89 21.54,203.72 57.81,389.09 78.87,587.01 -26.3,0.51 -43.93,-30.07 -56.96,-48.2 -46.9,-65.27 -86.02,-140.76 -127.04,-214.64 -52.84,-95.15 -108.23,-192.84 -157.71,-293.52 -75.25,-153.09 -188.6,-501.89 -242.12,-678.81 -8.67,-28.67 -17.7,-58.08 -26.3,-87.64 -7.48,-25.72 -10.39,-57.68 -35.05,-74.46 -100.02,18.93 -89.71,104.89 -70.09,205.9 47.35,243.43 170.89,706.45 211.48,946.04 -72.97,-70.97 -153.99,-207.41 -289.14,-236.55 -136.47,-29.44 -217.95,47.68 -271.6,122.66 -17.14,23.96 -41.43,49.54 -26.29,78.84 83.96,35.51 113.37,-65.2 197.15,-74.47 22.65,-2.5 54.56,2.4 74.46,8.78 132.4,42.34 237.57,218.76 297.87,346.07 74.16,156.45 125.32,330.5 148.95,490.64 -65.71,11.4 -142.96,22.15 -219.25,36.52 -109.8,20.72 -158.81,10.75 -201.29,59.86 9.15,41.95 41.41,60.8 70.1,83.24 126.26,-16.84 252.45,-33.77 372.36,-56.97 20.43,89.25 51.98,218.51 74.45,311.05 40.53,26.02 88.88,-8.43 105.17,-35.06 z" />
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<solid android:color="@color/widget_divider" />
|
|
||||||
</shape>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Material Icons "coffee_outlined", matches the in-app period ruler. -->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M18.52 3H6C4.92 3 3.98 3.89 3.98 5.02V10.69C3.98 14.53 6.94 17.91 10.78 18C14.72 18.14 18 14.95 18 11.02V9.98H18.52C20.44 9.98 21.98 8.44 21.98 6.52C21.98 4.55 20.44 3 18.52 3ZM15.98 5.02V8.02H6V5.02H15.98ZM15.98 9.98V11.02C15.98 13.78 13.78 15.98 11.02 15.98C8.25 15.98 6 13.78 6 11.02V9.98ZM18.52 8.02H18V5.02H18.52C19.31 5.02 20.02 5.67 20.02 6.52C20.02 7.31 19.31 8.02 18.52 8.02ZM3.98 18.98H20.02V21H3.98V18.98Z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Material Icons "event_outlined", matches the in-app holiday region. -->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M18.98 3.98H18V2.02H15.98V3.98H8.02V2.02H6V3.98H5.02C3.89 3.98 3 4.92 3 6V20.02C3 21.09 3.89 21.98 5.02 21.98H18.98C20.11 21.98 21 21.09 21 20.02V6C21 4.92 20.11 3.98 18.98 3.98ZM18.98 20.02H5.02V9.98H18.98V20.02ZM18.98 8.02H5.02V6H18.98V8.02ZM12 12.98H17.02V18H12V12.98Z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Material Icons "restaurant", matches the in-app break region. -->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M11.02 9H9V2.02H6.98V9H5.02V2.02H3V9C3 11.11 4.64 12.84 6.75 12.98V21.98H9.23V12.98C11.34 12.84 12.98 11.11 12.98 9V2.02H11.02V9ZM15.98 6V14.02H18.52V21.98H21V2.02C18.23 2.02 15.98 4.22 15.98 6Z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Tinted at runtime with the tile colour resolved in Dart. -->
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<corners android:radius="7dp" />
|
|
||||||
<solid android:color="@android:color/white" />
|
|
||||||
</shape>
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item>
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<corners android:radius="7dp" />
|
|
||||||
<solid android:color="@android:color/transparent" />
|
|
||||||
<stroke android:width="2dp" android:color="#C8F44336" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
<item
|
|
||||||
android:left="2dp"
|
|
||||||
android:top="2dp"
|
|
||||||
android:right="2dp"
|
|
||||||
android:bottom="2dp"
|
|
||||||
android:drawable="@drawable/widget_lesson_cancelled_x" />
|
|
||||||
</layer-list>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="100dp"
|
|
||||||
android:height="100dp"
|
|
||||||
android:viewportWidth="100"
|
|
||||||
android:viewportHeight="100">
|
|
||||||
<path
|
|
||||||
android:strokeColor="#C8F44336"
|
|
||||||
android:strokeWidth="2.5"
|
|
||||||
android:pathData="M0,0 L100,100 M100,0 L0,100" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="oval">
|
|
||||||
<solid android:color="@android:color/white" />
|
|
||||||
</shape>
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/background"
|
||||||
|
style="@style/Widget.Android.AppWidget.Container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:padding="0dp"
|
||||||
|
android:theme="@style/Theme.Android.AppWidgetContainer">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/widget_image"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_marginLeft="0dp"
|
||||||
|
android:layout_marginTop="0dp"
|
||||||
|
android:layout_marginBottom="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:adjustViewBounds="false"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@drawable/timetable_widget_default"
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</RelativeLayout>
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/widget_break_block_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="14dp"
|
|
||||||
android:layout_marginTop="0dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/widget_break_block_icon"
|
|
||||||
android:layout_width="12dp"
|
|
||||||
android:layout_height="12dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:src="@drawable/widget_icon_restaurant" />
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/widget_break_label_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="14dp"
|
|
||||||
android:layout_marginTop="0dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/widget_break_label_icon"
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:src="@drawable/widget_icon_coffee" />
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- FrameLayout root so the Marianum watermark can sit at bottom|end behind
|
|
||||||
the actual widget content without disturbing the LinearLayout flow.
|
|
||||||
Text sizes and chrome heights are dp: WidgetRenderer derives the grid
|
|
||||||
height from them, so they must not follow the system font scale. -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/widget_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@drawable/app_widget_background"
|
|
||||||
tools:ignore="SpUsage,SmallSp">
|
|
||||||
|
|
||||||
<!-- Width/height/end+bottom margins are overridden in the renderer so
|
|
||||||
the mark scales with the widget size. -->
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/widget_watermark"
|
|
||||||
android:layout_width="160dp"
|
|
||||||
android:layout_height="160dp"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:alpha="0.025"
|
|
||||||
android:src="@drawable/marianum_m_watermark" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_day_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:autoSizeTextType="uniform"
|
|
||||||
android:autoSizeMinTextSize="9dp"
|
|
||||||
android:autoSizeMaxTextSize="14dp"
|
|
||||||
android:autoSizeStepGranularity="0.5dp"
|
|
||||||
tools:text="Heute · 08.05." />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_day_subtitle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="6dp"
|
|
||||||
android:textSize="10dp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="Stand: 14:32" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- Narrow day widgets can't fit title and freshness side by side —
|
|
||||||
the renderer moves the freshness label down here instead. -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_day_subtitle_below"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="12dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:textSize="9dp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="Stand: 14:32" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_day_time_labels"
|
|
||||||
android:layout_width="30dp"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_day_grid"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_day_empty"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:textSize="13sp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="12dp"
|
|
||||||
tools:text="Keine Stunden" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Static picker preview of the day widget, laid out like WidgetRenderer's output. -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_background"
|
|
||||||
tools:ignore="SpUsage,SmallSp,HardcodedText,UseAppTint">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="160dp"
|
|
||||||
android:layout_height="160dp"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_marginEnd="-28dp"
|
|
||||||
android:layout_marginBottom="-28dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:alpha="0.018"
|
|
||||||
android:src="@drawable/marianum_m_watermark" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:textSize="14dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="Heute · 06.05." />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<FrameLayout android:layout_width="30dp" android:layout_height="match_parent">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="0dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="07:55" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="1" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="08:40" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="36dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="08:40" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="2" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="09:25" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="72dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="09:30" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="3" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="10:15" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp">
|
|
||||||
<ImageView android:layout_width="10dp" android:layout_height="10dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_text_secondary" android:src="@drawable/widget_icon_coffee" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="122dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="10:35" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="4" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="11:20" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="158dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="11:25" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="5" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="12:10" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="194dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="12:15" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="6" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="13:00" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="230dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="13:05" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="7" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="13:50" />
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp" android:background="@color/widget_preview_break">
|
|
||||||
<ImageView android:layout_width="12dp" android:layout_height="12dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_preview_accent" android:src="@drawable/widget_icon_restaurant" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="0.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#5C6BC0">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="MA-LK" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="B11" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="MUE" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="72.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#993333">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="DE" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A204" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="SCHN" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="122.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#0097A7">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="EN" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="F2.04" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="KRA" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="158.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#000000">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="BIO" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="N103" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="WEB" />
|
|
||||||
</LinearLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/widget_lesson_cancelled_overlay" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="230.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#29639B">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="GE" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A110" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="BER" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/widget_grid_line_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
android:background="@drawable/widget_grid_line" />
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Mirrors the in-app holiday region: icon and "Schulfrei" on top, the
|
|
||||||
holiday name rotated along the column. The name's width is set by the
|
|
||||||
renderer — after the rotation it is the length along the column. -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/widget_holiday_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:ignore="SpUsage,SmallSp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center_horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/widget_holiday_icon"
|
|
||||||
android:layout_width="14dp"
|
|
||||||
android:layout_height="14dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:src="@drawable/widget_icon_event" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_holiday_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="12dp"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:paddingStart="2dp"
|
|
||||||
android:paddingEnd="2dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/widget_school_free"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:autoSizeTextType="uniform"
|
|
||||||
android:autoSizeMinTextSize="6dp"
|
|
||||||
android:autoSizeMaxTextSize="9dp"
|
|
||||||
android:autoSizeStepGranularity="0.5dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_holiday_name"
|
|
||||||
android:layout_width="120dp"
|
|
||||||
android:layout_height="14dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:rotation="90"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:letterSpacing="0.1"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:autoSizeTextType="uniform"
|
|
||||||
android:autoSizeMinTextSize="7dp"
|
|
||||||
android:autoSizeMaxTextSize="11dp"
|
|
||||||
android:autoSizeStepGranularity="0.5dp"
|
|
||||||
tools:text="Herbstferien" />
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Mirrors AppointmentTile: title on top, room and teacher stacked below,
|
|
||||||
each line shrinking on its own to fit the tile width. Text sizes are dp
|
|
||||||
(not sp) because the line boxes are sized in dp by the renderer. -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/widget_lesson_block_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_marginStart="1dp"
|
|
||||||
android:layout_marginEnd="1dp"
|
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
android:background="@drawable/widget_lesson_block"
|
|
||||||
tools:ignore="SpUsage,SmallSp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingStart="4dp"
|
|
||||||
android:paddingEnd="4dp"
|
|
||||||
android:paddingTop="2dp"
|
|
||||||
android:paddingBottom="2dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/widget_lesson_title_row"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:baselineAligned="false">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_lesson_subject"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="14dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:fontFamily="sans-serif-medium"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:autoSizeTextType="uniform"
|
|
||||||
android:autoSizeMinTextSize="6.5dp"
|
|
||||||
android:autoSizeMaxTextSize="15dp"
|
|
||||||
android:autoSizeStepGranularity="0.5dp"
|
|
||||||
tools:text="MA-LK" />
|
|
||||||
|
|
||||||
<!-- Only for tiles too short for a body line below the title. -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_lesson_inline"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="7dp"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:text="B11" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_lesson_room"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:autoSizeTextType="uniform"
|
|
||||||
android:autoSizeMinTextSize="5.5dp"
|
|
||||||
android:autoSizeMaxTextSize="10dp"
|
|
||||||
android:autoSizeStepGranularity="0.5dp"
|
|
||||||
tools:text="A12" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_lesson_teacher"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:autoSizeTextType="uniform"
|
|
||||||
android:autoSizeMinTextSize="5.5dp"
|
|
||||||
android:autoSizeMaxTextSize="10dp"
|
|
||||||
android:autoSizeStepGranularity="0.5dp"
|
|
||||||
tools:text="Müller" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_lesson_cancelled"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@drawable/widget_lesson_cancelled_overlay"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_lesson_sibling_badge"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:layout_marginBottom="2dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="9dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:text="+1" />
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/widget_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@drawable/app_widget_background">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/widget_watermark"
|
|
||||||
android:layout_width="160dp"
|
|
||||||
android:layout_height="160dp"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:alpha="0.025"
|
|
||||||
android:src="@drawable/marianum_m_watermark" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_placeholder_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
tools:text="Marianum Vertretungsplan" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_placeholder_message"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
tools:text="Bitte einloggen, um den Stundenplan zu laden" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- One period cell of the ruler, mirroring the in-app _PeriodLabel: number
|
|
||||||
centred, start time above, end time below. -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/widget_time_label_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="36dp"
|
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
tools:ignore="SpUsage,SmallSp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_time_label_start"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="top"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:textSize="7dp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="07:55" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_time_label_number"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:fontFamily="sans-serif-medium"
|
|
||||||
android:textSize="11dp"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="1" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_time_label_end"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:layout_marginBottom="2dp"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:textSize="7dp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="08:40" />
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- FrameLayout root so the Marianum watermark can sit at bottom|end behind
|
|
||||||
the actual widget content without disturbing the LinearLayout flow.
|
|
||||||
Text sizes and chrome heights are dp: WidgetRenderer derives the grid
|
|
||||||
height from them, so they must not follow the system font scale. -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/widget_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@drawable/app_widget_background"
|
|
||||||
tools:ignore="SpUsage,SmallSp">
|
|
||||||
|
|
||||||
<!-- Width/height/end+bottom margins are overridden in the renderer so
|
|
||||||
the mark scales with the widget size. -->
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/widget_watermark"
|
|
||||||
android:layout_width="160dp"
|
|
||||||
android:layout_height="160dp"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:alpha="0.025"
|
|
||||||
android:src="@drawable/marianum_m_watermark" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_week_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:autoSizeTextType="uniform"
|
|
||||||
android:autoSizeMinTextSize="9dp"
|
|
||||||
android:autoSizeMaxTextSize="14dp"
|
|
||||||
android:autoSizeStepGranularity="0.5dp"
|
|
||||||
tools:text="KW 19 · 06.05.–10.05." />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_week_subtitle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="6dp"
|
|
||||||
android:textSize="10dp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="Stand: 14:32" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="30dp"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_header_mon"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_header_tue"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_header_wed"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_header_thu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_header_fri"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_time_labels"
|
|
||||||
android:layout_width="30dp"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_col_mon"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_col_tue"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_col_wed"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_col_thu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_divider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/widget_week_col_fri"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Mirrors the in-app _DayHeaderCell: weekday in caps, day number below,
|
|
||||||
today inside an accent circle. -->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/widget_week_day_header_root"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center"
|
|
||||||
tools:ignore="SpUsage,SmallSp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_week_day_header_weekday"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fontFamily="sans-serif-medium"
|
|
||||||
android:textSize="9dp"
|
|
||||||
android:textColor="@color/widget_text_secondary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="MO." />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/widget_week_day_header_date"
|
|
||||||
android:layout_width="18dp"
|
|
||||||
android:layout_height="18dp"
|
|
||||||
android:layout_marginTop="1dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="11dp"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
tools:text="6" />
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,336 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Static picker preview of the week widget, laid out like WidgetRenderer's output. -->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/widget_background"
|
|
||||||
tools:ignore="SpUsage,SmallSp,HardcodedText,UseAppTint">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_marginEnd="-36dp"
|
|
||||||
android:layout_marginBottom="-36dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:alpha="0.018"
|
|
||||||
android:src="@drawable/marianum_m_watermark" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:textSize="14dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/widget_text_primary"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="KW 19 · 04.05.–08.05." />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
<FrameLayout android:layout_width="30dp" android:layout_height="match_parent" />
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="9dp" android:textColor="@color/widget_text_secondary" android:text="MO." />
|
|
||||||
<TextView android:layout_width="18dp" android:layout_height="18dp" android:layout_marginTop="1dp" android:gravity="center" android:includeFontPadding="false" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="4" />
|
|
||||||
</LinearLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="9dp" android:textColor="@color/widget_text_secondary" android:text="DI." />
|
|
||||||
<TextView android:layout_width="18dp" android:layout_height="18dp" android:layout_marginTop="1dp" android:gravity="center" android:includeFontPadding="false" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="5" />
|
|
||||||
</LinearLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="9dp" android:textColor="@color/widget_text_secondary" android:text="MI." />
|
|
||||||
<TextView android:layout_width="18dp" android:layout_height="18dp" android:layout_marginTop="1dp" android:gravity="center" android:includeFontPadding="false" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="6" />
|
|
||||||
</LinearLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="9dp" android:textColor="@color/widget_text_secondary" android:text="DO." />
|
|
||||||
<TextView android:layout_width="18dp" android:layout_height="18dp" android:layout_marginTop="1dp" android:gravity="center" android:includeFontPadding="false" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="7" />
|
|
||||||
</LinearLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="9dp" android:textColor="@color/widget_text_secondary" android:text="FR." />
|
|
||||||
<TextView android:layout_width="18dp" android:layout_height="18dp" android:layout_marginTop="1dp" android:gravity="center" android:includeFontPadding="false" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="8" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<FrameLayout android:layout_width="30dp" android:layout_height="match_parent">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="0dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="07:55" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="1" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="08:40" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="36dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="08:40" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="2" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="09:25" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="72dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="09:30" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="3" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="10:15" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp">
|
|
||||||
<ImageView android:layout_width="10dp" android:layout_height="10dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_text_secondary" android:src="@drawable/widget_icon_coffee" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="122dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="10:35" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="4" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="11:20" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="158dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="11:25" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="5" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="12:10" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="194dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="12:15" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="6" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="13:00" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="36dp" android:layout_marginTop="230dp">
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_marginTop="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="13:05" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_horizontal" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:textSize="11dp" android:textColor="@color/widget_text_primary" android:text="7" />
|
|
||||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:gravity="center_horizontal" android:includeFontPadding="false" android:textSize="7dp" android:textColor="@color/widget_text_secondary" android:text="13:50" />
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp" android:background="@color/widget_preview_break">
|
|
||||||
<ImageView android:layout_width="12dp" android:layout_height="12dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_preview_accent" android:src="@drawable/widget_icon_restaurant" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="0.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#5C6BC0">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="MA-LK" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="B11" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="MUE" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="72.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#993333">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="DE" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A204" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="SCHN" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="122.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#0097A7">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="EN" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="F2.04" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="KRA" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="158.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#000000">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="BIO" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="N103" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="WEB" />
|
|
||||||
</LinearLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/widget_lesson_cancelled_overlay" />
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp" android:background="@color/widget_preview_break">
|
|
||||||
<ImageView android:layout_width="12dp" android:layout_height="12dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_preview_accent" android:src="@drawable/widget_icon_restaurant" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="0.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#26A69A">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="SPO" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="TH1" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="BAU" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="36.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#8F19B3">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="PoWi" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A105" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="HOF" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="84.5dp" android:layout_marginTop="72.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#29639B">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="PH" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="N201" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="LEH" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="158.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#9E9D24">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="GE" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A110" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="BER" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp" android:background="@color/widget_preview_break">
|
|
||||||
<ImageView android:layout_width="12dp" android:layout_height="12dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_preview_accent" android:src="@drawable/widget_icon_restaurant" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="0.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#E91E63">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="CH" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="N305" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="MEI" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="72.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#5C6BC0">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="MA-LK" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="B11" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="MUE" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="122.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#993333">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="DE" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A204" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="SCHN" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="194.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#0097A7">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="EN" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="F2.04" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="KRA" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp" android:background="@color/widget_preview_break">
|
|
||||||
<ImageView android:layout_width="12dp" android:layout_height="12dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_preview_accent" android:src="@drawable/widget_icon_restaurant" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="0.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#78909C">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="EK" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A301" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="LAN" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="36.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#993333">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="BIO" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="N103" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="WEB" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="122.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#7E57C2">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="MU" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="M1" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="SIN" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="158.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#F4511E">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="KU" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="K2" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="MAL" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="1dp" android:layout_height="match_parent" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1">
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="0dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="36dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="72dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="108dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="14dp" android:layout_marginTop="108dp" android:background="@color/widget_preview_break">
|
|
||||||
<ImageView android:layout_width="12dp" android:layout_height="12dp" android:layout_gravity="center" android:importantForAccessibility="no" android:contentDescription="@null" android:tint="@color/widget_preview_accent" android:src="@drawable/widget_icon_restaurant" />
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="122dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="158dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="194dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="230dp" android:background="@color/widget_divider" />
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="70.5dp" android:layout_marginTop="0.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#993333">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="PH" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="N201" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="LEH" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="72.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#FFA000">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="LA" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A108" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="CIC" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
<FrameLayout android:layout_width="match_parent" android:layout_height="34.5dp" android:layout_marginTop="122.8dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:background="@drawable/widget_lesson_block" android:backgroundTint="#9E9D24">
|
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingStart="4dp" android:paddingEnd="4dp" android:paddingTop="2dp" android:paddingBottom="2dp">
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:fontFamily="sans-serif-medium" android:maxLines="1" android:textSize="11dp" android:textColor="@android:color/white" android:text="GE" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="A110" />
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:textSize="8dp" android:textColor="@android:color/white" android:text="BER" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<inset
|
|
||||||
android:drawable="@drawable/ic_launcher_foreground"
|
|
||||||
android:inset="16%" />
|
|
||||||
</foreground>
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!--
|
||||||
|
Having themes.xml for night-v31 because of the priority order of the resource qualifiers.
|
||||||
|
-->
|
||||||
|
<style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
|
||||||
|
<item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
|
||||||
|
<item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="widget_background">#FF1F1716</color>
|
|
||||||
<color name="widget_text_primary">#FFF1F1F1</color>
|
|
||||||
<color name="widget_text_secondary">#FFB0B0B0</color>
|
|
||||||
<color name="widget_divider">#33FFFFFF</color>
|
|
||||||
<color name="widget_preview_accent">#FFFFB3AF</color>
|
|
||||||
<color name="widget_preview_break">#32FFB3AF</color>
|
|
||||||
</resources>
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
|
||||||
|
<item name="android:id">@android:id/background</item>
|
||||||
|
<item name="android:padding">?attr/appWidgetPadding</item>
|
||||||
|
<item name="android:background">@drawable/app_widget_background</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
|
||||||
|
<item name="android:padding">?attr/appWidgetPadding</item>
|
||||||
|
<item name="android:background">@drawable/app_widget_inner_view_background</item>
|
||||||
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -18,4 +18,18 @@
|
|||||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<item name="android:windowBackground">?android:colorBackground</item>
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
|
||||||
|
<item name="android:id">@android:id/background</item>
|
||||||
|
<item name="android:padding">?attr/appWidgetPadding</item>
|
||||||
|
<item name="android:background">@drawable/app_widget_background</item>
|
||||||
|
<item name="android:clipToOutline">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
|
||||||
|
<item name="android:padding">?attr/appWidgetPadding</item>
|
||||||
|
<item name="android:background">@drawable/app_widget_inner_view_background</item>
|
||||||
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
|
<item name="android:clipToOutline">true</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!--
|
||||||
|
Having themes.xml for v31 variant because @android:dimen/system_app_widget_background_radius
|
||||||
|
and @android:dimen/system_app_widget_internal_padding requires API level 31
|
||||||
|
-->
|
||||||
|
<style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
|
||||||
|
<item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
|
||||||
|
<item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<bool name="widget_supported">true</bool>
|
|
||||||
</resources>
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<resources>
|
||||||
|
<declare-styleable name="AppWidgetAttrs">
|
||||||
|
<attr name="appWidgetPadding" format="dimension" />
|
||||||
|
<attr name="appWidgetInnerRadius" format="dimension" />
|
||||||
|
<attr name="appWidgetRadius" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Brand accent for notifications; mirrors LightAppTheme.marianumRed
|
<color name="light_blue_50">#FFE1F5FE</color>
|
||||||
(Color.fromARGB(255, 153, 51, 51)). Used as the FCM default
|
<color name="light_blue_200">#FF81D4FA</color>
|
||||||
notification color and must stay in sync with the Dart constant. -->
|
<color name="light_blue_600">#FF039BE5</color>
|
||||||
<color name="notification_accent">#993333</color>
|
<color name="light_blue_900">#FF01579B</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Refer to App Widget Documentation for margin information
|
||||||
|
http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
|
||||||
|
-->
|
||||||
|
<dimen name="widget_margin">0dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -1,18 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="widget_day_label">Marianum · Heute</string>
|
<string name="appwidget_text">Marianum Vertretungsplan</string>
|
||||||
<string name="widget_week_label">Marianum · Woche</string>
|
<string name="add_widget">Hinzufügen</string>
|
||||||
<string name="widget_day_description">Stundenplan und Vertretungen für den anstehenden Schultag.</string>
|
<string name="app_widget_description">Übersicht zum Vertretungsplan</string>
|
||||||
<string name="widget_week_description">Stundenplan und Vertretungen für die ganze Schulwoche.</string>
|
|
||||||
<string name="widget_no_lessons">Keine Stunden</string>
|
|
||||||
<string name="widget_holiday">Ferien</string>
|
|
||||||
<string name="widget_school_free">Schulfrei</string>
|
|
||||||
<string name="widget_login_required">Bitte einloggen, um den Stundenplan zu laden</string>
|
|
||||||
<string name="widget_loading">Lade…</string>
|
|
||||||
<string name="widget_status_label">Stand: %1$s</string>
|
|
||||||
<string name="widget_today">Heute</string>
|
|
||||||
<string name="widget_tomorrow">Morgen</string>
|
|
||||||
<string name="widget_placeholder_title">Marianum Stundenplan</string>
|
|
||||||
<string name="widget_calendar_week_prefix">KW</string>
|
|
||||||
<string name="widget_yesterday_prefix">gestern</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -19,4 +19,14 @@
|
|||||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<item name="android:windowBackground">?android:colorBackground</item>
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
|
||||||
|
<item name="android:id">@android:id/background</item>
|
||||||
|
<item name="android:background">?android:attr/colorBackground</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
|
||||||
|
<item name="android:background">?android:attr/colorBackground</item>
|
||||||
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
|
||||||
|
<!-- Radius of the outer bound of widgets to make the rounded corners -->
|
||||||
|
<item name="appWidgetRadius">16dp</item>
|
||||||
|
<!--
|
||||||
|
Radius of the inner view's bound of widgets to make the rounded corners.
|
||||||
|
It needs to be 8dp or less than the value of appWidgetRadius
|
||||||
|
-->
|
||||||
|
<item name="appWidgetInnerRadius">8dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Theme.Android.AppWidgetContainer" parent="Theme.Android.AppWidgetContainerParent">
|
||||||
|
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
|
||||||
|
<item name="appWidgetPadding">16dp</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="widget_background">#FFFCF7F5</color>
|
|
||||||
<color name="widget_text_primary">#FF111111</color>
|
|
||||||
<color name="widget_text_secondary">#FF555555</color>
|
|
||||||
<color name="widget_divider">#22000000</color>
|
|
||||||
<color name="widget_preview_accent">#FF904A47</color>
|
|
||||||
<color name="widget_preview_break">#32904A47</color>
|
|
||||||
</resources>
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- WidgetRenderer positions every tile with RemoteViews calls that only
|
|
||||||
exist from Android 12 (API 31). Below that the widgets are not
|
|
||||||
offered at all rather than showing up empty. -->
|
|
||||||
<bool name="widget_supported">false</bool>
|
|
||||||
</resources>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Auto-Backup rules for Android 11 and below.
|
|
||||||
Excludes the home_widget plugin's SharedPreferences file
|
|
||||||
(HomeWidgetPreferences) so the cached timetable — which contains
|
|
||||||
teacher names, room numbers and personal custom events — is not
|
|
||||||
uploaded to the user's Google Drive. -->
|
|
||||||
<full-backup-content>
|
|
||||||
<exclude domain="sharedpref" path="HomeWidgetPreferences.xml"/>
|
|
||||||
</full-backup-content>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Backup + device-transfer rules for Android 12+.
|
|
||||||
Excludes the home_widget plugin's SharedPreferences file
|
|
||||||
(HomeWidgetPreferences) so the cached timetable — which contains
|
|
||||||
teacher names, room numbers and personal custom events — is not
|
|
||||||
uploaded to the user's Google Drive or transferred to a new device.
|
|
||||||
The widget repopulates from a fresh Webuntis fetch after sign-in. -->
|
|
||||||
<data-extraction-rules>
|
|
||||||
<cloud-backup>
|
|
||||||
<exclude domain="sharedpref" path="HomeWidgetPreferences.xml"/>
|
|
||||||
</cloud-backup>
|
|
||||||
<device-transfer>
|
|
||||||
<exclude domain="sharedpref" path="HomeWidgetPreferences.xml"/>
|
|
||||||
</device-transfer>
|
|
||||||
</data-extraction-rules>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:initialLayout="@layout/widget_placeholder"
|
|
||||||
android:minWidth="110dp"
|
|
||||||
android:minHeight="180dp"
|
|
||||||
android:targetCellWidth="2"
|
|
||||||
android:targetCellHeight="5"
|
|
||||||
android:resizeMode="horizontal|vertical"
|
|
||||||
android:widgetCategory="home_screen"
|
|
||||||
android:updatePeriodMillis="0"
|
|
||||||
android:description="@string/widget_day_description"
|
|
||||||
android:previewLayout="@layout/widget_day_preview" />
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:initialLayout="@layout/widget_placeholder"
|
|
||||||
android:minWidth="320dp"
|
|
||||||
android:minHeight="240dp"
|
|
||||||
android:targetCellWidth="5"
|
|
||||||
android:targetCellHeight="5"
|
|
||||||
android:resizeMode="horizontal|vertical"
|
|
||||||
android:widgetCategory="home_screen"
|
|
||||||
android:updatePeriodMillis="0"
|
|
||||||
android:description="@string/widget_week_description"
|
|
||||||
android:previewLayout="@layout/widget_week_preview" />
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:description="@string/app_widget_description"
|
||||||
|
android:initialKeyguardLayout="@layout/timetable_widget"
|
||||||
|
android:initialLayout="@layout/timetable_widget"
|
||||||
|
android:minWidth="220dp"
|
||||||
|
android:minHeight="294dp"
|
||||||
|
android:minResizeWidth="110dp"
|
||||||
|
android:minResizeHeight="147dp"
|
||||||
|
android:previewImage="@drawable/timetable_widget_preview"
|
||||||
|
android:previewLayout="@layout/timetable_widget"
|
||||||
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:targetCellWidth="3"
|
||||||
|
android:targetCellHeight="4"
|
||||||
|
android:updatePeriodMillis="86400000"
|
||||||
|
android:widgetCategory="home_screen" />
|
||||||
@@ -2,60 +2,32 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
|
// [required] background_fetch
|
||||||
|
maven {
|
||||||
|
url "${project(':background_fetch').projectDir}/libs"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.layout.buildDirectory = file('../build')
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.buildDir = '../build'
|
||||||
subprojects {
|
subprojects {
|
||||||
project.layout.buildDirectory = rootProject.layout.buildDirectory.dir(project.name)
|
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||||
}
|
}
|
||||||
// AGP 9 enables built-in Kotlin, but Flutter's migrator pins
|
|
||||||
// android.builtInKotlin=false while the plugin ecosystem catches up. Most
|
|
||||||
// plugins honour that flag and fall back to KGP themselves; file_picker and
|
|
||||||
// background_downloader only check the AGP major version and silently skip
|
|
||||||
// applying KGP, which leaves their Kotlin sources uncompiled (missing
|
|
||||||
// FilePickerPlugin/BackgroundDownloaderPlugin at link time). Apply KGP for
|
|
||||||
// them as soon as AGP is on the project, i.e. before their android {} block
|
|
||||||
// runs. Drop this once both plugins ship a builtInKotlin-aware build script.
|
|
||||||
gradle.beforeProject { sub ->
|
|
||||||
if (!(sub.name in ['file_picker', 'background_downloader'])) return
|
|
||||||
sub.plugins.withId('com.android.library') {
|
|
||||||
sub.pluginManager.apply('org.jetbrains.kotlin.android')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pin every Android subproject to JVM 17 so plugins that ship Kotlin sources
|
|
||||||
// compiled with a higher target (e.g. receive_sharing_intent at 21) or stale
|
|
||||||
// Java compatibility (e.g. home_widget at 1.8) don't break the build under
|
|
||||||
// newer Gradle/Kotlin tooling. Registered before evaluationDependsOn so the
|
|
||||||
// afterEvaluate fires at the right point in the lifecycle.
|
|
||||||
subprojects { sub ->
|
|
||||||
sub.afterEvaluate {
|
|
||||||
if (sub.hasProperty('android')) {
|
|
||||||
sub.android {
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
// Some plugins (e.g. app_settings) hard-pin an older compileSdk
|
|
||||||
// than their transitive AndroidX deps require, which fails the
|
|
||||||
// AAR metadata check. Align every plugin with the app's
|
|
||||||
// compileSdk (flutter.compileSdkVersion) so the build passes.
|
|
||||||
compileSdkVersion 36
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sub.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = '17'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("clean", Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.layout.buildDirectory
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package_name("eu.mhsl.marianum.mobile.client")
|
|
||||||
|
|
||||||
# Service-Account-JSON für die Google Play Developer API. Pfad über die
|
|
||||||
# Umgebungsvariable SUPPLY_JSON_KEY setzen (die Datei selbst wird per
|
|
||||||
# .gitignore nicht eingecheckt).
|
|
||||||
json_key_file(ENV["SUPPLY_JSON_KEY"] || "fastlane/play-service-account.json")
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
default_platform(:android)
|
|
||||||
|
|
||||||
# Play-Store-Auslieferung über fastlane supply. Die Screenshots erzeugt
|
|
||||||
# ../tool/screenshots.sh (Demo-Login + integration_test) direkt in
|
|
||||||
# metadata/android/<locale>/images/. Texte/Changelogs liegen daneben in
|
|
||||||
# metadata/android/<locale>/.
|
|
||||||
platform :android do
|
|
||||||
desc "Nur Screenshots hochladen (verändert keine Texte/Binaries)"
|
|
||||||
lane :upload_screenshots do
|
|
||||||
upload_to_play_store(
|
|
||||||
skip_upload_apk: true,
|
|
||||||
skip_upload_aab: true,
|
|
||||||
skip_upload_metadata: true,
|
|
||||||
skip_upload_changelogs: true,
|
|
||||||
skip_upload_images: false,
|
|
||||||
skip_upload_screenshots: false,
|
|
||||||
metadata_path: "./fastlane/metadata/android",
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Store-Texte, Changelogs und Screenshots hochladen (keine Binaries)"
|
|
||||||
lane :upload_metadata do
|
|
||||||
upload_to_play_store(
|
|
||||||
skip_upload_apk: true,
|
|
||||||
skip_upload_aab: true,
|
|
||||||
metadata_path: "./fastlane/metadata/android",
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# fastlane-Plugins (aktuell keine). Datei vorhanden, damit `fastlane` das
|
|
||||||
# Plugin-Handling initialisiert.
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Fastlane – Play-Store-Screenshots & Upload
|
|
||||||
|
|
||||||
Schritt 2 der Play-Store-Automatisierung. Die App muss dafür **nicht** neu
|
|
||||||
gebaut werden – der Demo-Modus (`demo@`-Login) liefert die kompletten Inhalte
|
|
||||||
aus Fixtures.
|
|
||||||
|
|
||||||
## 1. Screenshots aufnehmen
|
|
||||||
|
|
||||||
Ein Gerät/Emulator (≥ Android 8) per `adb devices` sichtbar, dann aus dem
|
|
||||||
**Client**-Wurzelverzeichnis:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
tool/screenshots.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Fährt Phone (1080×1920), 7″ (1200×1920) und 10″ (1600×2560) nacheinander durch
|
|
||||||
(setzt die Displaygröße per `adb shell wm size/density`) und legt die PNGs in
|
|
||||||
`metadata/android/de-DE/images/{phone,sevenInch,tenInch}Screenshots/` ab.
|
|
||||||
|
|
||||||
- Nur eine Größe: `PROFILES="phone" tool/screenshots.sh`
|
|
||||||
- Profile-Build (flüssigere Frames): `BUILD_MODE=profile tool/screenshots.sh`
|
|
||||||
|
|
||||||
## 2. Hochladen
|
|
||||||
|
|
||||||
Service-Account-JSON der Google Play Developer API besorgen und referenzieren:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export SUPPLY_JSON_KEY=/pfad/zu/play-service-account.json
|
|
||||||
cd android
|
|
||||||
fastlane upload_screenshots # nur Bilder
|
|
||||||
# oder
|
|
||||||
fastlane upload_metadata # Bilder + Texte/Changelogs, keine Binaries
|
|
||||||
```
|
|
||||||
|
|
||||||
Der Service-Account-Key wird **nicht** eingecheckt (siehe `.gitignore`).
|
|
||||||