add frontend and put backend in seperate folder
20
Dockerfile
@ -1,4 +1,9 @@
|
|||||||
# Stage 1: Build the Rust binary
|
FROM ghcr.io/cirruslabs/flutter:latest AS frontend_builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY frontend /app
|
||||||
|
RUN flutter build web --release
|
||||||
|
|
||||||
FROM rust AS builder
|
FROM rust AS builder
|
||||||
|
|
||||||
# Install necessary tools and dependencies
|
# Install necessary tools and dependencies
|
||||||
@ -6,13 +11,15 @@ FROM rust AS builder
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy the Rust project files
|
# Copy the Rust project files
|
||||||
COPY ./src /app/src
|
COPY backend/src /app/src
|
||||||
COPY ./scripts /app/scripts
|
COPY backend/scripts /app/scripts
|
||||||
COPY Cargo.lock /app
|
COPY backend/Cargo.lock /app
|
||||||
COPY Cargo.toml /app
|
COPY backend/Cargo.toml /app
|
||||||
|
|
||||||
|
COPY --from=frontend_builder /app/build/web /app/web
|
||||||
|
|
||||||
# Build the Rust binary
|
# Build the Rust binary
|
||||||
RUN cargo build --release
|
RUN cargo build --release --features static
|
||||||
|
|
||||||
# Stage 2: Create the final image
|
# Stage 2: Create the final image
|
||||||
FROM archlinux
|
FROM archlinux
|
||||||
@ -20,6 +27,7 @@ FROM archlinux
|
|||||||
# Copy the built binary from the previous stage
|
# Copy the built binary from the previous stage
|
||||||
COPY --from=builder /app/target/release/untitled /usr/local/bin/untitled
|
COPY --from=builder /app/target/release/untitled /usr/local/bin/untitled
|
||||||
|
|
||||||
|
|
||||||
RUN pacman -Syyu --noconfirm
|
RUN pacman -Syyu --noconfirm
|
||||||
RUN pacman -S --noconfirm base-devel git
|
RUN pacman -S --noconfirm base-devel git
|
||||||
RUN pacman -Sc
|
RUN pacman -Sc
|
||||||
|
63
Cargo.lock → backend/Cargo.lock
generated
@ -2156,6 +2156,40 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed"
|
||||||
|
version = "8.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "810294a8a4a0853d4118e3b94bb079905f2107c7fe979d8f0faae98765eb6378"
|
||||||
|
dependencies = [
|
||||||
|
"rust-embed-impl",
|
||||||
|
"rust-embed-utils",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed-impl"
|
||||||
|
version = "8.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfc144a1273124a67b8c1d7cd19f5695d1878b31569c0512f6086f0f4676604e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rust-embed-utils",
|
||||||
|
"syn 2.0.42",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed-utils"
|
||||||
|
version = "8.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "816ccd4875431253d6bb54b804bcff4369cbde9bae33defde25fdf6c2ef91d40"
|
||||||
|
dependencies = [
|
||||||
|
"sha2",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust_decimal"
|
name = "rust_decimal"
|
||||||
version = "1.33.1"
|
version = "1.33.1"
|
||||||
@ -2233,6 +2267,15 @@ version = "1.0.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
@ -3346,6 +3389,7 @@ dependencies = [
|
|||||||
"reqwest",
|
"reqwest",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_okapi",
|
"rocket_okapi",
|
||||||
|
"rust-embed",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"sea-orm-migration",
|
"sea-orm-migration",
|
||||||
"serde",
|
"serde",
|
||||||
@ -3409,6 +3453,16 @@ version = "0.9.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -3528,6 +3582,15 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
@ -20,9 +20,12 @@ rocket_okapi = { version = "0.8.0-rc.3", features = ["swagger"] }
|
|||||||
sea-orm = { version = "0.12", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] }
|
sea-orm = { version = "0.12", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] }
|
||||||
sea-orm-migration = {version = "0.12", features = ["sqlx-sqlite", "runtime-tokio-rustls"]}
|
sea-orm-migration = {version = "0.12", features = ["sqlx-sqlite", "runtime-tokio-rustls"]}
|
||||||
serde = "1.0.193"
|
serde = "1.0.193"
|
||||||
|
rust-embed = "8.1.0"
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "untitled"
|
name = "untitled"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
static = []
|
@ -20,5 +20,6 @@ pub fn build_api() -> Vec<Route> {
|
|||||||
version_del,
|
version_del,
|
||||||
build_output,
|
build_output,
|
||||||
list_builds,
|
list_builds,
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
51
backend/src/api/embed.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use rocket::http::uri::fmt::Path;
|
||||||
|
use rocket::http::uri::Segments;
|
||||||
|
use rocket::http::{ContentType, Method, Status};
|
||||||
|
use rocket::route::{Handler, Outcome};
|
||||||
|
use rocket::{Data, Request, Response, Route};
|
||||||
|
use rust_embed::{RustEmbed};
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "web"]
|
||||||
|
struct Asset;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CustomHandler {}
|
||||||
|
|
||||||
|
impl Into<Vec<Route>> for CustomHandler {
|
||||||
|
fn into(self) -> Vec<Route> {
|
||||||
|
vec![Route::ranked(-2, Method::Get, "/<path..>", self)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rocket::async_trait]
|
||||||
|
impl Handler for CustomHandler {
|
||||||
|
async fn handle<'r>(&self, request: &'r Request<'_>, _: Data<'r>) -> Outcome<'r> {
|
||||||
|
let mut path = request
|
||||||
|
.segments::<Segments<'_, Path>>(0..)
|
||||||
|
.ok()
|
||||||
|
.and_then(|segments| segments.to_path_buf(true).ok())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if path.is_dir() || path.to_str() == Some("") {
|
||||||
|
path = path.join("index.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
match <Asset as RustEmbed>::get(path.to_string_lossy().as_ref()) {
|
||||||
|
None => Outcome::Failure(Status::NotFound),
|
||||||
|
Some(file_content) => {
|
||||||
|
let content_type: ContentType = path
|
||||||
|
.extension()
|
||||||
|
.map(|x| x.to_string_lossy())
|
||||||
|
.and_then(|x| ContentType::from_extension(&x))
|
||||||
|
.unwrap_or(ContentType::Plain);
|
||||||
|
let rsp = Response::build()
|
||||||
|
.header(content_type)
|
||||||
|
.sized_body(file_content.data.len(), Cursor::new(file_content.data))
|
||||||
|
.finalize();
|
||||||
|
Outcome::Success(rsp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,3 +2,5 @@ mod add;
|
|||||||
pub mod backend;
|
pub mod backend;
|
||||||
mod list;
|
mod list;
|
||||||
mod remove;
|
mod remove;
|
||||||
|
#[cfg(feature = "static")]
|
||||||
|
pub mod embed;
|
@ -16,6 +16,8 @@ use sea_orm::{Database, DatabaseConnection};
|
|||||||
use sea_orm_migration::MigratorTrait;
|
use sea_orm_migration::MigratorTrait;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
|
#[cfg(feature = "static")]
|
||||||
|
use crate::api::embed::CustomHandler;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let t = tokio::runtime::Runtime::new().unwrap();
|
let t = tokio::runtime::Runtime::new().unwrap();
|
||||||
@ -50,20 +52,25 @@ fn main() {
|
|||||||
config.address = "0.0.0.0".parse().unwrap();
|
config.address = "0.0.0.0".parse().unwrap();
|
||||||
config.port = 8081;
|
config.port = 8081;
|
||||||
|
|
||||||
let launch_result = rocket::custom(config)
|
let rock = rocket::custom(config)
|
||||||
.manage(db)
|
.manage(db)
|
||||||
.manage(tx)
|
.manage(tx)
|
||||||
.mount("/", backend::build_api())
|
.mount("/", backend::build_api())
|
||||||
|
|
||||||
.mount(
|
.mount(
|
||||||
"/docs/",
|
"/docs/",
|
||||||
make_swagger_ui(&SwaggerUIConfig {
|
make_swagger_ui(&SwaggerUIConfig {
|
||||||
url: "../openapi.json".to_owned(),
|
url: "../openapi.json".to_owned(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
)
|
);
|
||||||
|
#[cfg(feature = "static")]
|
||||||
|
let rock = rock.mount("/", CustomHandler {});
|
||||||
|
|
||||||
|
let rock = rock
|
||||||
.launch()
|
.launch()
|
||||||
.await;
|
.await;
|
||||||
match launch_result {
|
match rock {
|
||||||
Ok(_) => println!("Rocket shut down gracefully."),
|
Ok(_) => println!("Rocket shut down gracefully."),
|
||||||
Err(err) => println!("Rocket had an error: {}", err),
|
Err(err) => println!("Rocket had an error: {}", err),
|
||||||
};
|
};
|
43
frontend/.gitignore
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
migrate_working_dir/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# The .vscode folder contains launch configuration and tasks you configure in
|
||||||
|
# VS Code which you may wish to be included in version control, so this line
|
||||||
|
# is commented out by default.
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
**/ios/Flutter/.last_build_id
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Symbolication related
|
||||||
|
app.*.symbols
|
||||||
|
|
||||||
|
# Obfuscation related
|
||||||
|
app.*.map.json
|
||||||
|
|
||||||
|
# Android Studio will place build artifacts here
|
||||||
|
/android/app/debug
|
||||||
|
/android/app/profile
|
||||||
|
/android/app/release
|
45
frontend/.metadata
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# This file tracks properties of this Flutter project.
|
||||||
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
|
#
|
||||||
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
|
version:
|
||||||
|
revision: "b0366e0a3f089e15fd89c97604ab402fe26b724c"
|
||||||
|
channel: "stable"
|
||||||
|
|
||||||
|
project_type: app
|
||||||
|
|
||||||
|
# Tracks metadata for the flutter migrate command
|
||||||
|
migration:
|
||||||
|
platforms:
|
||||||
|
- platform: root
|
||||||
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
- platform: android
|
||||||
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
- platform: ios
|
||||||
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
- platform: linux
|
||||||
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
- platform: macos
|
||||||
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
- platform: web
|
||||||
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
- platform: windows
|
||||||
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
|
||||||
|
# User provided section
|
||||||
|
|
||||||
|
# List of Local paths (relative to this file) that should be
|
||||||
|
# ignored by the migrate tool.
|
||||||
|
#
|
||||||
|
# Files that are not part of the templates will be ignored by default.
|
||||||
|
unmanaged_files:
|
||||||
|
- 'lib/main.dart'
|
||||||
|
- 'ios/Runner.xcodeproj/project.pbxproj'
|
16
frontend/README.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# aurcache
|
||||||
|
|
||||||
|
A new Flutter project.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
This project is a starting point for a Flutter application.
|
||||||
|
|
||||||
|
A few resources to get you started if this is your first Flutter project:
|
||||||
|
|
||||||
|
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||||
|
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||||
|
|
||||||
|
For help getting started with Flutter development, view the
|
||||||
|
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||||
|
samples, guidance on mobile development, and a full API reference.
|
28
frontend/analysis_options.yaml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
|
# check for errors, warnings, and lints.
|
||||||
|
#
|
||||||
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
|
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||||
|
# invoked from the command line by running `flutter analyze`.
|
||||||
|
|
||||||
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
# The lint rules applied to this project can be customized in the
|
||||||
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
# included above or to enable additional rules. A list of all available lints
|
||||||
|
# and their documentation is published at https://dart.dev/lints.
|
||||||
|
#
|
||||||
|
# Instead of disabling a lint rule for the entire project in the
|
||||||
|
# section below, it can also be suppressed for a single line of code
|
||||||
|
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||||
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
|
# producing the lint.
|
||||||
|
rules:
|
||||||
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
6
frontend/assets/icons/Documents.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="15.429" viewBox="0 0 12 15.429">
|
||||||
|
<g id="Group_785" data-name="Group 785" transform="translate(-279 -215)">
|
||||||
|
<path id="Vector" d="M11.864,6.612H7.091a1.628,1.628,0,0,1-1.157-.484,1.662,1.662,0,0,1-.479-1.169V.138a.138.138,0,0,0-.04-.1.136.136,0,0,0-.1-.04H2.182A2.171,2.171,0,0,0,.639.646,2.216,2.216,0,0,0,0,2.2v11.02a2.216,2.216,0,0,0,.639,1.559,2.171,2.171,0,0,0,1.543.646H9.818a2.171,2.171,0,0,0,1.543-.646A2.216,2.216,0,0,0,12,13.224V6.75a.138.138,0,0,0-.04-.1A.136.136,0,0,0,11.864,6.612Z" transform="translate(279 215)" fill="#2697ff"/>
|
||||||
|
<path id="Vector-2" data-name="Vector" d="M5.019,4.973.116.02a.068.068,0,0,0-.1.01A.069.069,0,0,0,0,.069v4.47a.554.554,0,0,0,.16.39.543.543,0,0,0,.386.161H4.971a.068.068,0,0,0,.038-.012.069.069,0,0,0,.025-.031.069.069,0,0,0-.015-.075Z" transform="translate(285.545 215.42)" fill="#2697ff"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 916 B |
6
frontend/assets/icons/Search.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="13.811" height="13.572" viewBox="0 0 13.811 13.572">
|
||||||
|
<g id="Search" transform="translate(-1165.25 -48.25)" opacity="0.8">
|
||||||
|
<path id="Vector" d="M10.286,5.041a5.093,5.093,0,0,1-5.143,5.041A5.093,5.093,0,0,1,0,5.041,5.093,5.093,0,0,1,5.143,0,5.093,5.093,0,0,1,10.286,5.041Z" transform="translate(1166 49)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
|
||||||
|
<path id="Vector-2" data-name="Vector" d="M2.571,2.52,0,0" transform="translate(1175.429 58.241)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 660 B |
11
frontend/assets/icons/drop_box.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14.655" height="14.88" viewBox="0 0 14.655 14.88">
|
||||||
|
<g id="Group" transform="translate(-918 -214)">
|
||||||
|
<path id="Vector" d="M3.837,2.249a.346.346,0,0,1-.178-.05L0,0V3.914L4.87,6.842V.966L4.127,2.093A.347.347,0,0,1,3.837,2.249Z" transform="translate(920.102 222.038)" fill="#007ee5"/>
|
||||||
|
<path id="Vector-2" data-name="Vector" d="M6.654,1.092,4.9,0,0,2.943,1.758,4.036Z" transform="translate(918 214.061)" fill="#007ee5"/>
|
||||||
|
<path id="Vector-3" data-name="Vector" d="M5.965,2.987,1,0,0,1.513,4.968,4.5Z" transform="translate(918.864 218.972)" fill="#007ee5"/>
|
||||||
|
<path id="Vector-4" data-name="Vector" d="M4.89,0,0,2.94,4.89,5.88,9.78,2.94Z" transform="translate(920.429 215.563)" fill="#007ee5"/>
|
||||||
|
<path id="Vector-5" data-name="Vector" d="M3.114,1.115,0,2.987,1.007,4.5,5.975,1.514,4.968,0Z" transform="translate(925.808 218.971)" fill="#007ee5"/>
|
||||||
|
<path id="Vector-6" data-name="Vector" d="M0,1.147,4.9,4.094,6.679,2.947,1.778,0Z" transform="translate(925.976 214)" fill="#007ee5"/>
|
||||||
|
<path id="Vector-7" data-name="Vector" d="M1.045,2.242a.347.347,0,0,1-.289-.155L0,.951V6.834L4.87,3.907V0L1.223,2.192A.346.346,0,0,1,1.045,2.242Z" transform="translate(925.666 222.046)" fill="#007ee5"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
3
frontend/assets/icons/folder.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="19" viewBox="0 0 25 19">
|
||||||
|
<path id="Vector" d="M25,4.354a2.7,2.7,0,0,0-.854-1.959,3,3,0,0,0-2.062-.812H10.631a1.292,1.292,0,0,1-.693-.2L8.49.466A3.015,3.015,0,0,0,6.869,0H2.917A3,3,0,0,0,.854.812,2.7,2.7,0,0,0,0,2.771V5.146a.386.386,0,0,0,.122.28.428.428,0,0,0,.295.116H24.583a.428.428,0,0,0,.295-.116A.386.386,0,0,0,25,5.146ZM0,16.229a2.7,2.7,0,0,0,.854,1.959A3,3,0,0,0,2.917,19H22.083a3,3,0,0,0,2.062-.812A2.7,2.7,0,0,0,25,16.229V7.521a.386.386,0,0,0-.122-.28.428.428,0,0,0-.295-.116H.417a.428.428,0,0,0-.295.116A.386.386,0,0,0,0,7.521Z" fill="#ffcf26"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 624 B |
11
frontend/assets/icons/logo.svg
Normal file
After Width: | Height: | Size: 84 KiB |
3
frontend/assets/icons/media.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="22" viewBox="0 0 26 22">
|
||||||
|
<path id="Vector" d="M23.231,0H2.769A2.755,2.755,0,0,0,.811.819,2.81,2.81,0,0,0,0,2.8V19.2a2.81,2.81,0,0,0,.811,1.977A2.755,2.755,0,0,0,2.769,22H23.231a2.755,2.755,0,0,0,1.958-.819A2.81,2.81,0,0,0,26,19.2V2.8A2.81,2.81,0,0,0,25.189.819,2.755,2.755,0,0,0,23.231,0ZM9.177,15.475V6.525L16.837,11Z" fill="#26e5ff"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 405 B |
3
frontend/assets/icons/menu_dashbord.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="14" viewBox="0 0 13 14">
|
||||||
|
<path id="Vector" d="M12.994,2.169V4.278a2.281,2.281,0,0,1-.559,1.537,1.886,1.886,0,0,1-1.384.652h-.8a.592.592,0,0,1,0-1.161h.772a.878.878,0,0,0,.649-.3,1.063,1.063,0,0,0,.262-.719V2.169a.972.972,0,0,0-.911-1H9.1a.959.959,0,0,0-.911,1V5.332a.563.563,0,0,1-.543.57.5.5,0,0,1-.37-.181.61.61,0,0,1-.143-.416V2.169A2.276,2.276,0,0,1,7.71.636,1.881,1.881,0,0,1,9.1,0h1.924A2.123,2.123,0,0,1,12.994,2.169ZM3.9,0H1.973A2.09,2.09,0,0,0,0,2.169V4.284A2.083,2.083,0,0,0,1.973,6.446H3.9a1.88,1.88,0,0,0,1.394-.631A2.276,2.276,0,0,0,5.87,4.284V2.169A2.084,2.084,0,0,0,3.9,0Zm.911,4.284A1.063,1.063,0,0,1,4.546,5a.879.879,0,0,1-.649.3H1.973a.87.87,0,0,1-.662-.293,1.056,1.056,0,0,1-.267-.728V2.169a1.053,1.053,0,0,1,.273-.715.869.869,0,0,1,.656-.286H3.9a.966.966,0,0,1,.911,1Zm4.3,3.27h1.924A2.083,2.083,0,0,1,13,9.716v2.116A2.09,2.09,0,0,1,11.027,14H9.1a2.085,2.085,0,0,1-1.967-2.169V9.716A2.071,2.071,0,0,1,9.1,7.554Zm2.57,4.988a1.048,1.048,0,0,0,.265-.71V9.716a1.054,1.054,0,0,0-.267-.708.871.871,0,0,0-.644-.293H9.1a.959.959,0,0,0-.911,1v2.116a1.048,1.048,0,0,0,.265.71.865.865,0,0,0,.646.291h1.924A.865.865,0,0,0,11.673,12.541ZM0,11.825V9.716A2.275,2.275,0,0,1,.578,8.185a1.88,1.88,0,0,1,1.394-.631h.79a.516.516,0,0,1,.507.271.633.633,0,0,1,0,.619.516.516,0,0,1-.507.271h-.79a.965.965,0,0,0-.917,1V11.8a.984.984,0,0,0,.917,1H3.909a.87.87,0,0,0,.648-.291,1.054,1.054,0,0,0,.269-.71V8.668a.608.608,0,0,1,.238-.6.492.492,0,0,1,.594.019.614.614,0,0,1,.206.613v3.124a2.078,2.078,0,0,1-1.973,2.169H1.973A2.122,2.122,0,0,1,0,11.825Z" fill="#00162a" opacity="0.6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
3
frontend/assets/icons/menu_doc.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="15" viewBox="0 0 13 15">
|
||||||
|
<path id="Vector" d="M12.841,4.167,8.979.183A.574.574,0,0,0,8.567.009H8.41L8.39,0a.082.082,0,0,0-.024,0,.087.087,0,0,0-.025,0l-.019,0H3.495A3.486,3.486,0,0,0,0,3.391V6.51a.572.572,0,0,0,1.144,0V3.391A2.333,2.333,0,0,1,3.495,1.142h4.3V2.764a2.526,2.526,0,0,0,2.529,2.511h0a.566.566,0,1,0,0-1.133A1.386,1.386,0,0,1,8.938,2.764V1.777l2.918,3.011v6.694a2.392,2.392,0,0,1-2.271,2.386H3.495a2.344,2.344,0,0,1-2.351-2.386V9.589A.572.572,0,0,0,0,9.589v1.892A3.47,3.47,0,0,0,3.495,15H9.585A3.514,3.514,0,0,0,13,11.481V4.56A.565.565,0,0,0,12.841,4.167ZM4.107,10.8H8.222a.566.566,0,1,0,0-1.133H4.107a.566.566,0,1,0,0,1.133ZM6.665,7.065H4.107a.566.566,0,1,1,0-1.133H6.665a.566.566,0,1,1,0,1.133Z" fill="#fff"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 792 B |
3
frontend/assets/icons/menu_notification.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16">
|
||||||
|
<path id="Vector" d="M13.445,7.447A3.185,3.185,0,0,1,14,9.088l-.022.148a3.252,3.252,0,0,1-.774,2.2,4.069,4.069,0,0,1-2.572,1.232,34.465,34.465,0,0,1-7.306,0A4.022,4.022,0,0,1,.8,11.439,3.207,3.207,0,0,1,0,9.249v-.1A3.3,3.3,0,0,1,.6,7.469L.659,7.4A3.035,3.035,0,0,0,1.389,5.99V4.54a.631.631,0,0,1,.653-.381.619.619,0,0,1,.553.507v1.45a.353.353,0,0,1,0,.077A4.166,4.166,0,0,1,1.586,8.151a1.982,1.982,0,0,0-.321,1v.155a2.022,2.022,0,0,0,.482,1.373,2.768,2.768,0,0,0,1.71.788,33.927,33.927,0,0,0,7.073,0,2.773,2.773,0,0,0,1.746-.824,2,2,0,0,0,.46-1.33V9.151a2.056,2.056,0,0,0-.314-1.007,4.175,4.175,0,0,1-1.067-1.957.358.358,0,0,1,0-.077V4.653C11.143,2.527,8.944,1.211,7.03,1.211a4.853,4.853,0,0,0-2.323.584.649.649,0,0,1-.639,0A.595.595,0,0,1,4.093.739,6.108,6.108,0,0,1,6.971,0C9.5,0,12.334,1.732,12.656,4.512v1.45a2.973,2.973,0,0,0,.731,1.408A.538.538,0,0,1,13.445,7.447Zm-6.238,7.3a1.641,1.641,0,0,0,1.072-.624h.007a.647.647,0,0,1,.888-.081.592.592,0,0,1,.084.855,2.926,2.926,0,0,1-4.581,0,.592.592,0,0,1,.084-.855.647.647,0,0,1,.888.081,1.661,1.661,0,0,0,1.558.624Z" fill="#00162a" opacity="0.6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
3
frontend/assets/icons/menu_profile.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="15" viewBox="0 0 10 15">
|
||||||
|
<path id="Vector" d="M2.536,4.015A2.735,2.735,0,0,1,5,1.078,2.735,2.735,0,0,1,7.464,4.015,2.735,2.735,0,0,1,5,6.952,2.735,2.735,0,0,1,2.536,4.015Zm-.9,0C1.633,6.229,3.143,8.03,5,8.03s3.367-1.8,3.367-4.015S6.857,0,5,0,1.633,1.8,1.633,4.015ZM4.361,14.989Q4.675,15,5,15c2.147,0,5-.286,5-2.752,0-2.768-3.764-2.768-5-2.768-2.147,0-5,.286-5,2.753a2.362,2.362,0,0,0,1.66,2.29.438.438,0,0,0,.573-.338A.567.567,0,0,0,1.95,13.5C1.011,13.124.9,12.6.9,12.233c0-1.112,1.379-1.676,4.1-1.676s4.1.569,4.1,1.691S7.718,13.922,5,13.922q-.311,0-.613-.01a.547.547,0,0,0-.026,1.076Z" fill="#00162a" opacity="0.6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 686 B |
3
frontend/assets/icons/menu_setting.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="15" viewBox="0 0 13 15">
|
||||||
|
<path id="Vector" d="M4.408,3.656a1.713,1.713,0,0,1-1.813-.013L2.57,3.617A.6.6,0,0,1,2.4,2.826a.516.516,0,0,1,.739-.184.732.732,0,0,0,.369.112.723.723,0,0,0,.54-.212.829.829,0,0,0,.241-.559A1.92,1.92,0,0,1,6.078,0h.843A1.915,1.915,0,0,1,8.767,1.976a.8.8,0,0,0,.1.4.755.755,0,0,0,.453.376.7.7,0,0,0,.569-.08,1.78,1.78,0,0,1,2.462.711.61.61,0,0,1-.2.784.522.522,0,0,1-.732-.2.724.724,0,0,0-1.022-.29,1.741,1.741,0,0,1-1.809-.021,2,2,0,0,1-.924-1.665A.829.829,0,0,0,7.456,1.4a.722.722,0,0,0-.535-.243H6.078A.727.727,0,0,0,5.54,1.4a.835.835,0,0,0-.213.581A1.97,1.97,0,0,1,4.408,3.656Zm.919,9.388a.778.778,0,0,0,.751.8l-.006.013a.53.53,0,0,1,.464.287.608.608,0,0,1,0,.573A.53.53,0,0,1,6.071,15a1.915,1.915,0,0,1-1.846-1.976.8.8,0,0,0-.1-.4.725.725,0,0,0-1.022-.3,1.78,1.78,0,0,1-2.462-.711l-.418-.784A2.056,2.056,0,0,1,.89,8.2a.792.792,0,0,0,.271-.29.842.842,0,0,0,.122-.637A.794.794,0,0,0,.92,6.752,2.056,2.056,0,0,1,.256,4.117.535.535,0,0,1,.6,3.873a.507.507,0,0,1,.4.087.592.592,0,0,1,.154.764A.828.828,0,0,0,1.431,5.81a1.887,1.887,0,0,1,.64.718,2.055,2.055,0,0,1-.665,2.635A.828.828,0,0,0,1.13,10.25l.425.784a.742.742,0,0,0,.453.378.691.691,0,0,0,.569-.088,1.689,1.689,0,0,1,.9-.257A1.915,1.915,0,0,1,5.327,13.043ZM12.1,8.2a.793.793,0,0,1-.348-.486.847.847,0,0,1,.077-.607.793.793,0,0,1,.271-.29.6.6,0,0,0,.185-.784.529.529,0,0,0-.726-.217A2.055,2.055,0,0,0,10.9,8.445a1.868,1.868,0,0,0,.671.784.785.785,0,0,1,.348.483.839.839,0,0,1-.077.6l-.418.784a.779.779,0,0,1-.455.375.691.691,0,0,1-.566-.086,1.741,1.741,0,0,0-1.812.023,2,2,0,0,0-.921,1.67.539.539,0,0,0,1.077,0,.8.8,0,0,1,.369-.7.7.7,0,0,1,.751.008,1.78,1.78,0,0,0,2.462-.711l.419-.784A2.056,2.056,0,0,0,12.1,8.2ZM6.5,5.026A2.318,2.318,0,0,0,4.358,6.557a2.606,2.606,0,0,0,.5,2.7,2.2,2.2,0,0,0,2.524.533A2.486,2.486,0,0,0,8.81,7.5a2.561,2.561,0,0,0-.678-1.749A2.233,2.233,0,0,0,6.5,5.026Zm0,3.794A1.276,1.276,0,0,1,5.265,7.5,1.276,1.276,0,0,1,6.5,6.186,1.276,1.276,0,0,1,7.727,7.5,1.276,1.276,0,0,1,6.5,8.821Z" fill="#00162a" opacity="0.6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
3
frontend/assets/icons/menu_store.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="15" viewBox="0 0 13 15">
|
||||||
|
<path id="Vector" d="M12.934,10.31l-.517-4.4c-.331-1.978-1.527-2.637-2.537-2.637A3.628,3.628,0,0,0,7.559.174,3.176,3.176,0,0,0,4.032,1.226a.622.622,0,0,0-.118.566.552.552,0,0,0,.388.4.5.5,0,0,0,.506-.17V1.951a2.168,2.168,0,0,1,3.258-.2,2.66,2.66,0,0,1,.745,1.516H3.173c-.968,0-2.14.659-2.537,2.67l-.15.989a.574.574,0,0,0,.436.631.531.531,0,0,0,.6-.433l.144-.969c.222-1.1.781-1.76,1.5-1.76H9.881c.757,0,1.316.659,1.5,1.714l.511,4.358a3.567,3.567,0,0,1-.391,2.578,2.657,2.657,0,0,1-2.23.771H3.786a2.728,2.728,0,0,1-2.17-.857,3.285,3.285,0,0,1-.451-2.492A.57.57,0,0,0,.72,9.816a.535.535,0,0,0-.6.488,3.971,3.971,0,0,0,.692,3.412,3.222,3.222,0,0,0,2.974,1.256H9.268A3.528,3.528,0,0,0,12.273,13.8,4.671,4.671,0,0,0,12.934,10.31ZM8.216,7.522a.684.684,0,0,0,.234.053.577.577,0,0,0,.421-.2.527.527,0,0,0,.144-.218.6.6,0,0,0,.048-.251.468.468,0,0,0,0-.132.421.421,0,0,0-.036-.125.273.273,0,0,0-.054-.112.917.917,0,0,0-.162-.185.729.729,0,0,0-.222-.1.473.473,0,0,0-.234,0,.4.4,0,0,0-.114.04.441.441,0,0,0-.108.059l-.09.086a.288.288,0,0,0-.072.1l-.06.112v.125a.478.478,0,0,0,0,.132.593.593,0,0,0,.042.251A.652.652,0,0,0,8.216,7.522ZM5.228,6.915a.632.632,0,0,1-.6.659.578.578,0,0,1-.409-.2.667.667,0,0,1-.132-.218.716.716,0,0,1-.042-.251.47.47,0,0,1,0-.132.423.423,0,0,1,.036-.125.383.383,0,0,1,.054-.112.286.286,0,0,1,.072-.1.4.4,0,0,1,.09-.079A.327.327,0,0,1,4.4,6.3a.339.339,0,0,1,.114-.04.473.473,0,0,1,.234,0,.339.339,0,0,1,.114.04.327.327,0,0,1,.1.059.4.4,0,0,1,.1.086.287.287,0,0,1,.072.1.674.674,0,0,1,.06.112l.036.125A.9.9,0,0,1,5.228,6.915Z" fill="#00162a" opacity="0.6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
3
frontend/assets/icons/menu_task.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
|
||||||
|
<path id="Vector" d="M13.992,5.48A6.347,6.347,0,0,0,8.009,0a1.056,1.056,0,0,0-.8.34,1.114,1.114,0,0,0-.288.821L7.23,5.981A1.144,1.144,0,0,0,8.347,7.059H8.42l4.6-.321a1.02,1.02,0,0,0,.718-.365A1.116,1.116,0,0,0,14,5.583v-.1ZM8.347,5.9,8.04,1.168a5.217,5.217,0,0,1,4.847,4.421Zm2.013,3.3a.562.562,0,0,1,.687-.4.555.555,0,0,1,.346.267.6.6,0,0,1,.059.446,6.045,6.045,0,0,1-2.816,3.728,5.587,5.587,0,0,1-5.477.087A6.081,6.081,0,0,1,.045,8.612,3.969,3.969,0,0,1,0,7.9,6.038,6.038,0,0,1,4.64,1.925a.565.565,0,0,1,.663.462.589.589,0,0,1-.442.693A4.889,4.889,0,0,0,1.125,7.919a3.251,3.251,0,0,0,.031.545,4.806,4.806,0,0,0,4.312,4.317A4.724,4.724,0,0,0,10.359,9.2Z" fill="#001b34" opacity="0.6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 780 B |
3
frontend/assets/icons/menu_tran.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="14" viewBox="0 0 13 14">
|
||||||
|
<path id="Vector" d="M13,6a.518.518,0,0,1-.5.536H12.5a.475.475,0,0,1-.352-.159A.552.552,0,0,1,12.005,6V4.377c0-2.13-1.092-3.306-3.07-3.306H4.065c-1.984,0-3.07,1.176-3.07,3.306V9.629c0,2.13,1.092,3.3,3.07,3.3H8.935c1.984,0,3.07-1.176,3.07-3.3a.5.5,0,1,1,.995,0C13,12.325,11.445,14,8.941,14H4.065C1.555,14,0,12.325,0,9.629V4.377C0,1.675,1.555,0,4.065,0H8.935C11.434,0,13,1.675,13,4.377ZM3.224,10.281V5.8a.548.548,0,0,1,.158-.371.471.471,0,0,1,.356-.14.483.483,0,0,1,.347.17.56.56,0,0,1,.133.384v4.476a.515.515,0,0,1-.515.517A.521.521,0,0,1,3.224,10.281Zm2.8-6.557v6.563a.5.5,0,1,0,.995,0V3.725a.5.5,0,1,0-.995,0Zm2.755,6.557V8.188a.5.5,0,1,1,.995,0v2.093a.5.5,0,1,1-.995,0Z" fill="#00162a" opacity="0.6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 797 B |
3
frontend/assets/icons/unknown.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="25" viewBox="0 0 18 25">
|
||||||
|
<path id="Vector" d="M17.473,5.357H12.6V.523ZM18,7.143V22.321a2.671,2.671,0,0,1-.792,1.893A2.714,2.714,0,0,1,15.3,25H2.7a2.714,2.714,0,0,1-1.908-.785A2.671,2.671,0,0,1,0,22.321V2.679A2.671,2.671,0,0,1,.792.785,2.714,2.714,0,0,1,2.7,0h8.1V6.25a.889.889,0,0,0,.264.631.9.9,0,0,0,.636.262Zm-8.1,12.5a.889.889,0,0,0-.264-.631.905.905,0,0,0-1.273,0,.888.888,0,0,0,0,1.263.905.905,0,0,0,1.273,0A.889.889,0,0,0,9.9,19.643Zm2.644-8.676A3.559,3.559,0,0,0,11.75,9.3a3.613,3.613,0,0,0-6.014.8,3.542,3.542,0,0,0-.337,1.51.889.889,0,0,0,.264.631.905.905,0,0,0,1.273,0,.889.889,0,0,0,.264-.631,1.782,1.782,0,0,1,.652-1.375,1.809,1.809,0,0,1,2.475.165,1.781,1.781,0,0,1-.64,2.861,2.621,2.621,0,0,0-1.167.98A2.59,2.59,0,0,0,8.1,15.7v1.268a.889.889,0,0,0,.264.631.905.905,0,0,0,1.273,0,.889.889,0,0,0,.264-.631V15.7a.834.834,0,0,1,.119-.464.844.844,0,0,1,.356-.324,3.584,3.584,0,0,0,1.789-1.589,3.54,3.54,0,0,0,.38-2.352Z" fill="#ee2727"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1016 B |
22
frontend/lib/core/constants/color_constants.dart
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const primaryColor = Color(0xFF2697FF);
|
||||||
|
//const secondaryColor = Color(0xFF2A2D3E);
|
||||||
|
//const bgColor = Color(0xFF212132);
|
||||||
|
|
||||||
|
const secondaryColor = Color(0xFF292929);
|
||||||
|
const bgColor = Color(0xFF212121);
|
||||||
|
const darkgreenColor = Color(0xFF2c614f);
|
||||||
|
const greenColor = Color(0xFF6bab58);
|
||||||
|
|
||||||
|
const defaultPadding = 16.0;
|
||||||
|
const double defaultBorderRadius = 15;
|
||||||
|
|
||||||
|
class ColorConstants {
|
||||||
|
static Color blue = Color(0xFF0D46BB);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Palette {
|
||||||
|
static const Color background = Color(0xFFEDEEF2);
|
||||||
|
static const Color wrapperBg = Color(0xFF212121);
|
||||||
|
}
|
22
frontend/lib/core/utils/colorful_tag.dart
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Color getRoleColor(String? role) {
|
||||||
|
if (role == "Doctor") {
|
||||||
|
return Colors.green;
|
||||||
|
} else if (role == "Software Architect") {
|
||||||
|
return Colors.red;
|
||||||
|
} else if (role == "Software Engineer") {
|
||||||
|
return Colors.blueAccent;
|
||||||
|
} else if (role == "Solution Architect") {
|
||||||
|
return Colors.amberAccent;
|
||||||
|
} else if (role == "Project Manager") {
|
||||||
|
return Colors.cyanAccent;
|
||||||
|
} else if (role == "Business Analyst") {
|
||||||
|
return Colors.deepPurpleAccent;
|
||||||
|
} else if (role == "UI/UX Designer") {
|
||||||
|
return Colors.indigoAccent;
|
||||||
|
}
|
||||||
|
return Colors.black38;
|
||||||
|
}
|
63
frontend/lib/core/widgets/app_button_widget.dart
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
enum ButtonType { PRIMARY, PLAIN }
|
||||||
|
|
||||||
|
class AppButton extends StatelessWidget {
|
||||||
|
final ButtonType? type;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final String? text;
|
||||||
|
|
||||||
|
AppButton({this.type, this.onPressed, this.text});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: this.onPressed,
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 45,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: getButtonColor(context, type!),
|
||||||
|
borderRadius: BorderRadius.circular(4.0),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
//color: Color.fromRGBO(169, 176, 185, 0.42),
|
||||||
|
//spreadRadius: 0,
|
||||||
|
//blurRadius: 3.0,
|
||||||
|
//offset: Offset(0, 2),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(this.text!,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.subtitle1!
|
||||||
|
.copyWith(color: getTextColor(context, type!))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getButtonColor(context, ButtonType type) {
|
||||||
|
switch (type) {
|
||||||
|
case ButtonType.PRIMARY:
|
||||||
|
return Theme.of(context).buttonTheme.colorScheme!.background;
|
||||||
|
case ButtonType.PLAIN:
|
||||||
|
return Colors.white;
|
||||||
|
default:
|
||||||
|
return Theme.of(context).primaryColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getTextColor(context, ButtonType type) {
|
||||||
|
switch (type) {
|
||||||
|
case ButtonType.PLAIN:
|
||||||
|
return Theme.of(context).primaryColor;
|
||||||
|
case ButtonType.PRIMARY:
|
||||||
|
return Colors.white;
|
||||||
|
default:
|
||||||
|
return Theme.of(context).buttonTheme.colorScheme!.background;
|
||||||
|
}
|
||||||
|
}
|
94
frontend/lib/core/widgets/input_widget.dart
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../constants/color_constants.dart';
|
||||||
|
|
||||||
|
class InputWidget extends StatelessWidget {
|
||||||
|
final String? hintText;
|
||||||
|
final String? errorText;
|
||||||
|
final Widget? prefixIcon;
|
||||||
|
final double? height;
|
||||||
|
final String? topLabel;
|
||||||
|
final bool? obscureText;
|
||||||
|
final FormFieldSetter<String>? onSaved;
|
||||||
|
final ValueChanged<String>? onChanged;
|
||||||
|
final FormFieldValidator<String>? validator;
|
||||||
|
final TextInputType? keyboardType;
|
||||||
|
final Key? kKey;
|
||||||
|
final TextEditingController? kController;
|
||||||
|
final String? kInitialValue;
|
||||||
|
|
||||||
|
InputWidget({
|
||||||
|
this.hintText,
|
||||||
|
this.prefixIcon,
|
||||||
|
this.height = 48.0,
|
||||||
|
this.topLabel = "",
|
||||||
|
this.obscureText = false,
|
||||||
|
required this.onSaved,
|
||||||
|
this.keyboardType,
|
||||||
|
this.errorText,
|
||||||
|
this.onChanged,
|
||||||
|
this.validator,
|
||||||
|
this.kKey,
|
||||||
|
this.kController,
|
||||||
|
this.kInitialValue,
|
||||||
|
});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(this.topLabel!),
|
||||||
|
SizedBox(height: 4.0),
|
||||||
|
Container(
|
||||||
|
height: 50,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: secondaryColor,
|
||||||
|
//color: Theme.of(context).buttonColor,
|
||||||
|
borderRadius: BorderRadius.circular(4.0),
|
||||||
|
),
|
||||||
|
child: TextFormField(
|
||||||
|
initialValue: this.kInitialValue,
|
||||||
|
controller: this.kController,
|
||||||
|
key: this.kKey,
|
||||||
|
keyboardType: this.keyboardType,
|
||||||
|
onSaved: this.onSaved,
|
||||||
|
onChanged: this.onChanged,
|
||||||
|
validator: this.validator,
|
||||||
|
obscureText: this.obscureText!,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: this.prefixIcon,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color.fromRGBO(74, 77, 84, 0.2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
//gapPadding: 16,
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
errorStyle: TextStyle(height: 0, color: Colors.transparent),
|
||||||
|
errorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(context).errorColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedErrorBorder: OutlineInputBorder(
|
||||||
|
//gapPaddings: 16,
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(context).errorColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
hintText: this.hintText,
|
||||||
|
hintStyle: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyText1!
|
||||||
|
.copyWith(color: Colors.white54),
|
||||||
|
errorText: this.errorText),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
34
frontend/lib/core/widgets/wrapper.dart
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../constants/color_constants.dart';
|
||||||
|
|
||||||
|
class Wrapper extends StatelessWidget {
|
||||||
|
final Widget? title;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const Wrapper({Key? key, this.title, required this.child}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(defaultPadding),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Palette.wrapperBg,
|
||||||
|
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (title != null)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
title!,
|
||||||
|
const SizedBox(height: defaultPadding),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
31
frontend/lib/main.dart
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import 'package:aurcache/screens/home/home_screen.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import 'core/constants/color_constants.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(const MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
title: 'Smart Dashboard - Admin Panel v0.1 ',
|
||||||
|
theme: ThemeData.dark().copyWith(
|
||||||
|
appBarTheme: const AppBarTheme(backgroundColor: bgColor, elevation: 0),
|
||||||
|
scaffoldBackgroundColor: bgColor,
|
||||||
|
primaryColor: greenColor,
|
||||||
|
dialogBackgroundColor: secondaryColor,
|
||||||
|
textTheme: GoogleFonts.openSansTextTheme(Theme.of(context).textTheme)
|
||||||
|
.apply(bodyColor: Colors.white),
|
||||||
|
canvasColor: secondaryColor,
|
||||||
|
),
|
||||||
|
home: const HomeScreen(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
289
frontend/lib/models/daily_info_model.dart
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../core/constants/color_constants.dart';
|
||||||
|
|
||||||
|
class DailyInfoModel {
|
||||||
|
IconData? icon;
|
||||||
|
String? title;
|
||||||
|
String? totalStorage;
|
||||||
|
int? volumeData;
|
||||||
|
int? percentage;
|
||||||
|
Color? color;
|
||||||
|
List<Color>? colors;
|
||||||
|
List<FlSpot>? spots;
|
||||||
|
|
||||||
|
DailyInfoModel({
|
||||||
|
this.icon,
|
||||||
|
this.title,
|
||||||
|
this.totalStorage,
|
||||||
|
this.volumeData,
|
||||||
|
this.percentage,
|
||||||
|
this.color,
|
||||||
|
this.colors,
|
||||||
|
this.spots,
|
||||||
|
});
|
||||||
|
|
||||||
|
DailyInfoModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
title = json['title'];
|
||||||
|
volumeData = json['volumeData'];
|
||||||
|
icon = json['icon'];
|
||||||
|
totalStorage = json['totalStorage'];
|
||||||
|
color = json['color'];
|
||||||
|
percentage = json['percentage'];
|
||||||
|
colors = json['colors'];
|
||||||
|
spots = json['spots'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['title'] = this.title;
|
||||||
|
data['volumeData'] = this.volumeData;
|
||||||
|
data['icon'] = this.icon;
|
||||||
|
data['totalStorage'] = this.totalStorage;
|
||||||
|
data['color'] = this.color;
|
||||||
|
data['percentage'] = this.percentage;
|
||||||
|
data['colors'] = this.colors;
|
||||||
|
data['spots'] = this.spots;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DailyInfoModel> dailyDatas =
|
||||||
|
dailyData.map((item) => DailyInfoModel.fromJson(item)).toList();
|
||||||
|
|
||||||
|
//List<FlSpot> spots = yValues.asMap().entries.map((e) {
|
||||||
|
// return FlSpot(e.key.toDouble(), e.value);
|
||||||
|
//}).toList();
|
||||||
|
|
||||||
|
var dailyData = [
|
||||||
|
{
|
||||||
|
"title": "Employee",
|
||||||
|
"volumeData": 1328,
|
||||||
|
"icon": Icons.ac_unit,
|
||||||
|
"totalStorage": "+ %20",
|
||||||
|
"color": primaryColor,
|
||||||
|
"percentage": 35,
|
||||||
|
"colors": [
|
||||||
|
Color(0xff23b6e6),
|
||||||
|
Color(0xff02d39a),
|
||||||
|
],
|
||||||
|
"spots": [
|
||||||
|
FlSpot(
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
2,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
3,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
4,
|
||||||
|
1.5,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
5,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
6,
|
||||||
|
2.2,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
7,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
8,
|
||||||
|
1.5,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "On Leave",
|
||||||
|
"volumeData": 1328,
|
||||||
|
"icon": Icons.ac_unit,
|
||||||
|
"totalStorage": "+ %5",
|
||||||
|
"color": Color(0xFFFFA113),
|
||||||
|
"percentage": 35,
|
||||||
|
"colors": [Color(0xfff12711), Color(0xfff5af19)],
|
||||||
|
"spots": [
|
||||||
|
FlSpot(
|
||||||
|
1,
|
||||||
|
1.3,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
2,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
4,
|
||||||
|
1.5,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
5,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
6,
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
7,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
8,
|
||||||
|
1.5,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Onboarding",
|
||||||
|
"volumeData": 1328,
|
||||||
|
"icon": Icons.ac_unit,
|
||||||
|
"totalStorage": "+ %8",
|
||||||
|
"color": Color(0xFFA4CDFF),
|
||||||
|
"percentage": 10,
|
||||||
|
"colors": [Color(0xff2980B9), Color(0xff6DD5FA)],
|
||||||
|
"spots": [
|
||||||
|
FlSpot(
|
||||||
|
1,
|
||||||
|
1.3,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
2,
|
||||||
|
5,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
3,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
4,
|
||||||
|
6,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
5,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
6,
|
||||||
|
2.2,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
7,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
8,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Open Position",
|
||||||
|
"volumeData": 1328,
|
||||||
|
"icon": Icons.ac_unit,
|
||||||
|
"totalStorage": "+ %8",
|
||||||
|
"color": Color(0xFFd50000),
|
||||||
|
"percentage": 10,
|
||||||
|
"colors": [Color(0xff93291E), Color(0xffED213A)],
|
||||||
|
"spots": [
|
||||||
|
FlSpot(
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
3,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
4,
|
||||||
|
1.5,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
5,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
6,
|
||||||
|
2.2,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
7,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
8,
|
||||||
|
1.5,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Efficiency",
|
||||||
|
"volumeData": 5328,
|
||||||
|
"icon": Icons.ac_unit,
|
||||||
|
"totalStorage": "- %5",
|
||||||
|
"color": Color(0xFF00F260),
|
||||||
|
"percentage": 78,
|
||||||
|
"colors": [Color(0xff0575E6), Color(0xff00F260)],
|
||||||
|
"spots": [
|
||||||
|
FlSpot(
|
||||||
|
1,
|
||||||
|
1.3,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
2,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
3,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
4,
|
||||||
|
1.5,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
5,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
6,
|
||||||
|
2.2,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
7,
|
||||||
|
1.8,
|
||||||
|
),
|
||||||
|
FlSpot(
|
||||||
|
8,
|
||||||
|
1.5,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
//final List<double> yValues = [
|
||||||
|
// 2.3,
|
||||||
|
// 1.8,
|
||||||
|
// 1.9,
|
||||||
|
// 1.5,
|
||||||
|
// 1.0,
|
||||||
|
// 2.2,
|
||||||
|
// 1.8,
|
||||||
|
// 1.5,
|
||||||
|
//];
|
64
frontend/lib/models/slider_model.dart
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
class SliderModel {
|
||||||
|
String? image;
|
||||||
|
String? text;
|
||||||
|
String? altText;
|
||||||
|
String? bAltText;
|
||||||
|
String? productImage;
|
||||||
|
int? kBackgroundColor;
|
||||||
|
|
||||||
|
SliderModel(this.image, this.text, this.altText, this.bAltText,
|
||||||
|
this.productImage, this.kBackgroundColor);
|
||||||
|
|
||||||
|
SliderModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
image = json['image'];
|
||||||
|
kBackgroundColor = json['kBackgroundColor'];
|
||||||
|
text = json['text'];
|
||||||
|
altText = json['altText'];
|
||||||
|
bAltText = json['bAltText'];
|
||||||
|
productImage = json['productImage'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['image'] = this.image;
|
||||||
|
data['kBackgroundColor'] = this.kBackgroundColor;
|
||||||
|
data['text'] = this.text;
|
||||||
|
data['altText'] = this.altText;
|
||||||
|
data['bAltText'] = this.bAltText;
|
||||||
|
data['productImage'] = this.productImage;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SliderModel> slides =
|
||||||
|
slideData.map((item) => SliderModel.fromJson(item)).toList();
|
||||||
|
|
||||||
|
var slideData = [
|
||||||
|
{
|
||||||
|
"image": "assets/slides/background-1.jpeg",
|
||||||
|
"kBackgroundColor": 0xFF2c614f,
|
||||||
|
"text": "Welcome to the Smart Smart Admin Dashboard!",
|
||||||
|
"altText": "You can access & track your services in real-time.",
|
||||||
|
"bAltText": "Are you ready for the next generation AI supported Dashboard?",
|
||||||
|
"productImage": "assets/images/mockup.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"image": "assets/slides/background-2.jpeg",
|
||||||
|
"kBackgroundColor": 0xFF8a1a4c,
|
||||||
|
"text": "¡Bienvenido al tablero Smart Admin Dashboard!",
|
||||||
|
"altText": "Puede acceder y rastrear sus servicios en tiempo real.",
|
||||||
|
"bAltText":
|
||||||
|
"¿Estás listo para el panel de control impulsado por IA de próxima generación?",
|
||||||
|
"productImage": "assets/images/mockup-2.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"image": "assets/slides/background-3.jpeg",
|
||||||
|
"kBackgroundColor": 0xFF0ab3ec,
|
||||||
|
"text": "Willkommen im Smart Admin Dashboard!",
|
||||||
|
"altText":
|
||||||
|
"Sie können in Echtzeit auf Ihre Dienste zugreifen und diese verfolgen.",
|
||||||
|
"bAltText":
|
||||||
|
"Sind Sie bereit für das AI-unterstützte Dashboard der nächsten Generation?",
|
||||||
|
"productImage": "assets/images/mockup-3.png"
|
||||||
|
}
|
||||||
|
];
|
1
frontend/lib/providers/menu_provider.dart
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
44
frontend/lib/responsive.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Responsive extends StatelessWidget {
|
||||||
|
final Widget mobile;
|
||||||
|
final Widget tablet;
|
||||||
|
final Widget desktop;
|
||||||
|
|
||||||
|
const Responsive({
|
||||||
|
Key? key,
|
||||||
|
required this.mobile,
|
||||||
|
required this.tablet,
|
||||||
|
required this.desktop,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
// This size work fine on my design, maybe you need some customization depends on your design
|
||||||
|
|
||||||
|
// This isMobile, isTablet, isDesktop helep us later
|
||||||
|
static bool isMobile(BuildContext context) =>
|
||||||
|
MediaQuery.of(context).size.width < 850;
|
||||||
|
|
||||||
|
static bool isTablet(BuildContext context) =>
|
||||||
|
MediaQuery.of(context).size.width < 1100 &&
|
||||||
|
MediaQuery.of(context).size.width >= 850;
|
||||||
|
|
||||||
|
static bool isDesktop(BuildContext context) =>
|
||||||
|
MediaQuery.of(context).size.width >= 1100;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final Size _size = MediaQuery.of(context).size;
|
||||||
|
// If our width is more than 1100 then we consider it a desktop
|
||||||
|
if (_size.width >= 1100) {
|
||||||
|
return desktop;
|
||||||
|
}
|
||||||
|
// If width it less then 1100 and more then 850 we consider it as tablet
|
||||||
|
else if (_size.width >= 850) {
|
||||||
|
return tablet;
|
||||||
|
}
|
||||||
|
// Or less then that we called it mobile
|
||||||
|
else {
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
frontend/lib/screens/dashboard/components/charts.dart
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Chart extends StatefulWidget {
|
||||||
|
const Chart({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ChartState createState() => _ChartState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChartState extends State<Chart> {
|
||||||
|
int touchedIndex = -1;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 300,
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 1.3,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
const SizedBox(
|
||||||
|
height: 18,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 1,
|
||||||
|
child: PieChart(
|
||||||
|
PieChartData(
|
||||||
|
pieTouchData:
|
||||||
|
PieTouchData(touchCallback: (pieTouchResponse, touchresponse) {
|
||||||
|
setState(() {
|
||||||
|
// final desiredTouch = pieTouchResponse.touchInput
|
||||||
|
// is! PointerExitEvent &&
|
||||||
|
// pieTouchResponse.touchInput is! PointerUpEvent;
|
||||||
|
if ( touchresponse?.touchedSection != null) {
|
||||||
|
touchedIndex = touchresponse!.touchedSection!.touchedSectionIndex;
|
||||||
|
} else {
|
||||||
|
touchedIndex = -1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
borderData: FlBorderData(
|
||||||
|
show: false,
|
||||||
|
),
|
||||||
|
sectionsSpace: 0,
|
||||||
|
centerSpaceRadius: 40,
|
||||||
|
sections: showingSections()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 28,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PieChartSectionData> showingSections() {
|
||||||
|
return List.generate(2, (i) {
|
||||||
|
final isTouched = i == touchedIndex;
|
||||||
|
final fontSize = isTouched ? 25.0 : 16.0;
|
||||||
|
final radius = isTouched ? 60.0 : 50.0;
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return PieChartSectionData(
|
||||||
|
color: const Color(0xff760707),
|
||||||
|
value: 40,
|
||||||
|
title: '28.3%',
|
||||||
|
radius: radius,
|
||||||
|
titleStyle: TextStyle(
|
||||||
|
fontSize: fontSize,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: const Color(0xffffffff)),
|
||||||
|
);
|
||||||
|
case 1:
|
||||||
|
return PieChartSectionData(
|
||||||
|
color: const Color(0xff0a7005),
|
||||||
|
value: 30,
|
||||||
|
title: '16.7%',
|
||||||
|
radius: radius,
|
||||||
|
titleStyle: TextStyle(
|
||||||
|
fontSize: fontSize,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: const Color(0xffffffff)),
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw Error();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
117
frontend/lib/screens/dashboard/components/header.dart
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
import '../../../responsive.dart';
|
||||||
|
|
||||||
|
class Header extends StatelessWidget {
|
||||||
|
const Header({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
if (!Responsive.isDesktop(context))
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.menu),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
if (!Responsive.isMobile(context))
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Hello, Arch User 👋",
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Welcome to AURCentral",
|
||||||
|
style: Theme.of(context).textTheme.subtitle2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (!Responsive.isMobile(context))
|
||||||
|
Spacer(flex: Responsive.isDesktop(context) ? 2 : 1),
|
||||||
|
Expanded(child: SearchField()),
|
||||||
|
//ProfileCard()
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileCard extends StatelessWidget {
|
||||||
|
const ProfileCard({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.only(left: defaultPadding),
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: defaultPadding,
|
||||||
|
vertical: defaultPadding / 2,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: secondaryColor,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
border: Border.all(color: Colors.white10),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
CircleAvatar(
|
||||||
|
backgroundImage: AssetImage("assets/images/profile_pic.png"),
|
||||||
|
),
|
||||||
|
if (!Responsive.isMobile(context))
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: defaultPadding / 2),
|
||||||
|
child: Text("Deniz Çolak"),
|
||||||
|
),
|
||||||
|
Icon(Icons.keyboard_arrow_down),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchField extends StatelessWidget {
|
||||||
|
const SearchField({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TextField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Search",
|
||||||
|
fillColor: secondaryColor,
|
||||||
|
filled: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
suffixIcon: InkWell(
|
||||||
|
onTap: () {},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(defaultPadding * 0.75),
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: defaultPadding / 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: greenColor,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
"assets/icons/Search.svg",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
import '../../../models/daily_info_model.dart';
|
||||||
|
import '../../../responsive.dart';
|
||||||
|
import 'mini_information_widget.dart';
|
||||||
|
|
||||||
|
class MiniInformation extends StatelessWidget {
|
||||||
|
const MiniInformation({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final Size _size = MediaQuery.of(context).size;
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton.icon(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: defaultPadding * 1.5,
|
||||||
|
vertical:
|
||||||
|
defaultPadding / (Responsive.isMobile(context) ? 2 : 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.add),
|
||||||
|
label: Text(
|
||||||
|
"Add New",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: defaultPadding),
|
||||||
|
Responsive(
|
||||||
|
mobile: InformationCard(
|
||||||
|
crossAxisCount: _size.width < 650 ? 2 : 4,
|
||||||
|
childAspectRatio: _size.width < 650 ? 1.2 : 1,
|
||||||
|
),
|
||||||
|
tablet: InformationCard(),
|
||||||
|
desktop: InformationCard(
|
||||||
|
childAspectRatio: _size.width < 1400 ? 1.2 : 1.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InformationCard extends StatelessWidget {
|
||||||
|
const InformationCard({
|
||||||
|
Key? key,
|
||||||
|
this.crossAxisCount = 5,
|
||||||
|
this.childAspectRatio = 1,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final int crossAxisCount;
|
||||||
|
final double childAspectRatio;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GridView.builder(
|
||||||
|
physics: NeverScrollableScrollPhysics(),
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: dailyDatas.length,
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: crossAxisCount,
|
||||||
|
crossAxisSpacing: defaultPadding,
|
||||||
|
mainAxisSpacing: defaultPadding,
|
||||||
|
childAspectRatio: childAspectRatio,
|
||||||
|
),
|
||||||
|
itemBuilder: (context, index) =>
|
||||||
|
MiniInformationWidget(dailyData: dailyDatas[index]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,206 @@
|
|||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
import '../../../models/daily_info_model.dart';
|
||||||
|
|
||||||
|
class MiniInformationWidget extends StatefulWidget {
|
||||||
|
const MiniInformationWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.dailyData,
|
||||||
|
}) : super(key: key);
|
||||||
|
final DailyInfoModel dailyData;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_MiniInformationWidgetState createState() => _MiniInformationWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
int _value = 1;
|
||||||
|
|
||||||
|
class _MiniInformationWidgetState extends State<MiniInformationWidget> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(defaultPadding),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: secondaryColor,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(defaultPadding * 0.75),
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: widget.dailyData.color!.withOpacity(0.1),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
widget.dailyData.icon,
|
||||||
|
color: widget.dailyData.color,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(right: 12.0),
|
||||||
|
child: DropdownButton(
|
||||||
|
icon: Icon(Icons.more_vert, size: 18),
|
||||||
|
underline: SizedBox(),
|
||||||
|
style: Theme.of(context).textTheme.button,
|
||||||
|
value: _value,
|
||||||
|
items: [
|
||||||
|
DropdownMenuItem(
|
||||||
|
child: Text("Daily"),
|
||||||
|
value: 1,
|
||||||
|
),
|
||||||
|
DropdownMenuItem(
|
||||||
|
child: Text("Weekly"),
|
||||||
|
value: 2,
|
||||||
|
),
|
||||||
|
DropdownMenuItem(
|
||||||
|
child: Text("Monthly"),
|
||||||
|
value: 3,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
onChanged: (int? value) {
|
||||||
|
setState(() {
|
||||||
|
_value = value!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
widget.dailyData.title!,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child: LineChartWidget(
|
||||||
|
colors: widget.dailyData.colors,
|
||||||
|
spotsData: widget.dailyData.spots,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
ProgressLine(
|
||||||
|
color: widget.dailyData.color!,
|
||||||
|
percentage: widget.dailyData.percentage!,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"${widget.dailyData.volumeData}",
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.caption!
|
||||||
|
.copyWith(color: Colors.white70),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
widget.dailyData.totalStorage!,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.caption!
|
||||||
|
.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LineChartWidget extends StatelessWidget {
|
||||||
|
const LineChartWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.colors,
|
||||||
|
required this.spotsData,
|
||||||
|
}) : super(key: key);
|
||||||
|
final List<Color>? colors;
|
||||||
|
final List<FlSpot>? spotsData;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 80,
|
||||||
|
height: 30,
|
||||||
|
child: LineChart(
|
||||||
|
LineChartData(
|
||||||
|
lineBarsData: [
|
||||||
|
LineChartBarData(
|
||||||
|
spots: spotsData!,
|
||||||
|
belowBarData: BarAreaData(show: false),
|
||||||
|
aboveBarData: BarAreaData(show: false),
|
||||||
|
isCurved: true,
|
||||||
|
dotData: FlDotData(show: false),
|
||||||
|
//colors: colors,
|
||||||
|
barWidth: 3),
|
||||||
|
],
|
||||||
|
lineTouchData: LineTouchData(enabled: false),
|
||||||
|
titlesData: FlTitlesData(show: false),
|
||||||
|
//axisTitleData: FlAxisTitleData(show: false),
|
||||||
|
gridData: FlGridData(show: false),
|
||||||
|
borderData: FlBorderData(show: false)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProgressLine extends StatelessWidget {
|
||||||
|
const ProgressLine({
|
||||||
|
Key? key,
|
||||||
|
this.color = primaryColor,
|
||||||
|
required this.percentage,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final Color color;
|
||||||
|
final int percentage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 5,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: color.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
LayoutBuilder(
|
||||||
|
builder: (context, constraints) => Container(
|
||||||
|
width: constraints.maxWidth * (percentage / 100),
|
||||||
|
height: 5,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: color,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
65
frontend/lib/screens/dashboard/components/recent_builds.dart
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
|
||||||
|
class RecentBuilds extends StatelessWidget {
|
||||||
|
const RecentBuilds({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(defaultPadding),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: secondaryColor,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Recent Builds",
|
||||||
|
style: Theme.of(context).textTheme.subtitle1,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: DataTable(
|
||||||
|
horizontalMargin: 0,
|
||||||
|
columnSpacing: defaultPadding,
|
||||||
|
columns: [
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Build ID"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Package Name"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Version"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Status"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rows: List.generate(
|
||||||
|
7,
|
||||||
|
(index) => recentUserDataRow(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRow recentUserDataRow() {
|
||||||
|
return DataRow(
|
||||||
|
cells: [
|
||||||
|
DataCell(Text("1")),
|
||||||
|
DataCell(Text("Resources")),
|
||||||
|
DataCell(Text("v1.2.3")),
|
||||||
|
DataCell(Icon(Icons.watch_later_outlined, color: Color(0xFF9D8D00),)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
91
frontend/lib/screens/dashboard/components/recent_users.dart
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
|
||||||
|
class RecentUsers extends StatelessWidget {
|
||||||
|
const RecentUsers({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(defaultPadding),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: secondaryColor,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Your Packages",
|
||||||
|
style: Theme.of(context).textTheme.subtitle1,
|
||||||
|
),
|
||||||
|
SingleChildScrollView(
|
||||||
|
//scrollDirection: Axis.horizontal,
|
||||||
|
child: SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: DataTable(
|
||||||
|
horizontalMargin: 0,
|
||||||
|
columnSpacing: defaultPadding,
|
||||||
|
columns: [
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Package ID"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Package Name"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Number of versions"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Status"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text("Action"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rows: List.generate(
|
||||||
|
7,
|
||||||
|
(index) => recentUserDataRow(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRow recentUserDataRow(BuildContext context) {
|
||||||
|
return DataRow(
|
||||||
|
cells: [
|
||||||
|
DataCell(Text("1")),
|
||||||
|
DataCell(Text("Resources")),
|
||||||
|
DataCell(Text("2")),
|
||||||
|
DataCell(Icon(Icons.watch_later_outlined, color: Color(0xFF9D8D00),)),
|
||||||
|
DataCell(
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
child: Text('View', style: TextStyle(color: greenColor)),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 6,
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: Text("Delete", style: TextStyle(color: Colors.redAccent)),
|
||||||
|
onPressed: () {
|
||||||
|
|
||||||
|
},
|
||||||
|
// Delete
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
|
||||||
|
class UserDetailsMiniCard extends StatelessWidget {
|
||||||
|
const UserDetailsMiniCard({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.color,
|
||||||
|
required this.amountOfFiles,
|
||||||
|
required this.numberOfIncrease,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final Color color;
|
||||||
|
final String title, amountOfFiles;
|
||||||
|
final int numberOfIncrease;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.only(top: defaultPadding),
|
||||||
|
padding: EdgeInsets.all(defaultPadding),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)),
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(defaultPadding),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: Container(
|
||||||
|
color: color,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: defaultPadding),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"$numberOfIncrease",
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.caption!
|
||||||
|
.copyWith(color: Colors.white70),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(amountOfFiles)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
import 'package:aurcache/screens/dashboard/components/user_details_mini_card.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
import 'charts.dart';
|
||||||
|
|
||||||
|
class UserDetailsWidget extends StatelessWidget {
|
||||||
|
const UserDetailsWidget({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(defaultPadding),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: secondaryColor,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Package build success",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: defaultPadding),
|
||||||
|
Chart(),
|
||||||
|
UserDetailsMiniCard(
|
||||||
|
color: const Color(0xff0a7005),
|
||||||
|
title: "Successful Builds",
|
||||||
|
amountOfFiles: "%16.7",
|
||||||
|
numberOfIncrease: 1328,
|
||||||
|
),
|
||||||
|
UserDetailsMiniCard(
|
||||||
|
color: const Color(0xff760707),
|
||||||
|
title: "Failed Builds",
|
||||||
|
amountOfFiles: "%28.3",
|
||||||
|
numberOfIncrease: 1328,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
57
frontend/lib/screens/dashboard/dashboard_screen.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../core/constants/color_constants.dart';
|
||||||
|
import '../../responsive.dart';
|
||||||
|
import 'components/header.dart';
|
||||||
|
import 'components/mini_information_card.dart';
|
||||||
|
import 'components/recent_builds.dart';
|
||||||
|
import 'components/recent_users.dart';
|
||||||
|
import 'components/user_details_widget.dart';
|
||||||
|
|
||||||
|
class DashboardScreen extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SafeArea(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
//padding: EdgeInsets.all(defaultPadding),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(defaultPadding),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Header(),
|
||||||
|
SizedBox(height: defaultPadding),
|
||||||
|
MiniInformation(),
|
||||||
|
SizedBox(height: defaultPadding),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 5,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
RecentUsers(),
|
||||||
|
SizedBox(height: defaultPadding),
|
||||||
|
RecentBuilds(),
|
||||||
|
if (Responsive.isMobile(context))
|
||||||
|
SizedBox(height: defaultPadding),
|
||||||
|
if (Responsive.isMobile(context)) UserDetailsWidget(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!Responsive.isMobile(context))
|
||||||
|
SizedBox(width: defaultPadding),
|
||||||
|
// On Mobile means if the screen is less than 850 we dont want to show it
|
||||||
|
if (!Responsive.isMobile(context))
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: UserDetailsWidget(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
90
frontend/lib/screens/home/components/side_menu.dart
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
|
import '../../../core/constants/color_constants.dart';
|
||||||
|
|
||||||
|
class SideMenu extends StatelessWidget {
|
||||||
|
const SideMenu({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Drawer(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
// it enables scrolling
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
DrawerHeader(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
// SizedBox(
|
||||||
|
// height: defaultPadding * 3,
|
||||||
|
// ),
|
||||||
|
// Image.asset(
|
||||||
|
// "assets/logo/logo_icon.png",
|
||||||
|
// scale: 5,
|
||||||
|
// ),
|
||||||
|
SizedBox(
|
||||||
|
height: defaultPadding,
|
||||||
|
),
|
||||||
|
Text("AUR Build Server")
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
DrawerListTile(
|
||||||
|
title: "Dashboard",
|
||||||
|
svgSrc: "assets/icons/menu_dashbord.svg",
|
||||||
|
press: () {},
|
||||||
|
),
|
||||||
|
DrawerListTile(
|
||||||
|
title: "Builds",
|
||||||
|
svgSrc: "assets/icons/menu_tran.svg",
|
||||||
|
press: () {},
|
||||||
|
),
|
||||||
|
DrawerListTile(
|
||||||
|
title: "AUR",
|
||||||
|
svgSrc: "assets/icons/menu_task.svg",
|
||||||
|
press: () {},
|
||||||
|
),
|
||||||
|
DrawerListTile(
|
||||||
|
title: "Settings",
|
||||||
|
svgSrc: "assets/icons/menu_setting.svg",
|
||||||
|
press: () {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DrawerListTile extends StatelessWidget {
|
||||||
|
const DrawerListTile({
|
||||||
|
Key? key,
|
||||||
|
// For selecting those three line once press "Command+D"
|
||||||
|
required this.title,
|
||||||
|
required this.svgSrc,
|
||||||
|
required this.press,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String title, svgSrc;
|
||||||
|
final VoidCallback press;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
onTap: press,
|
||||||
|
horizontalTitleGap: 0.0,
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
svgSrc,
|
||||||
|
color: Colors.white54,
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(color: Colors.white54),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
35
frontend/lib/screens/home/home_screen.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../responsive.dart';
|
||||||
|
import '../dashboard/dashboard_screen.dart';
|
||||||
|
import 'components/side_menu.dart';
|
||||||
|
|
||||||
|
class HomeScreen extends StatelessWidget {
|
||||||
|
const HomeScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
drawer: const SideMenu(),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// We want this side menu only for large screen
|
||||||
|
if (Responsive.isDesktop(context))
|
||||||
|
const Expanded(
|
||||||
|
// default flex = 1
|
||||||
|
// and it takes 1/6 part of the screen
|
||||||
|
child: SideMenu(),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
// It takes 5/6 part of the screen
|
||||||
|
flex: 5,
|
||||||
|
child: DashboardScreen(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
1
frontend/linux/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
flutter/ephemeral
|
145
frontend/linux/CMakeLists.txt
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# Project-level configuration.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
|
# The name of the executable created for the application. Change this to change
|
||||||
|
# the on-disk name of your application.
|
||||||
|
set(BINARY_NAME "aurcache")
|
||||||
|
# The unique GTK application identifier for this application. See:
|
||||||
|
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||||
|
set(APPLICATION_ID "eu.heili.aurcentral.aurcache")
|
||||||
|
|
||||||
|
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||||
|
# versions of CMake.
|
||||||
|
cmake_policy(SET CMP0063 NEW)
|
||||||
|
|
||||||
|
# Load bundled libraries from the lib/ directory relative to the binary.
|
||||||
|
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||||
|
|
||||||
|
# Root filesystem for cross-building.
|
||||||
|
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
||||||
|
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
||||||
|
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Define build configuration options.
|
||||||
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||||
|
STRING "Flutter build mode" FORCE)
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||||
|
"Debug" "Profile" "Release")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Compilation settings that should be applied to most targets.
|
||||||
|
#
|
||||||
|
# Be cautious about adding new options here, as plugins use this function by
|
||||||
|
# default. In most cases, you should add new options to specific targets instead
|
||||||
|
# of modifying this function.
|
||||||
|
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||||
|
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||||
|
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||||
|
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||||
|
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Flutter library and tool build rules.
|
||||||
|
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||||
|
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||||
|
|
||||||
|
# System-level dependencies.
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
|
|
||||||
|
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||||
|
|
||||||
|
# Define the application target. To change its name, change BINARY_NAME above,
|
||||||
|
# not the value here, or `flutter run` will no longer work.
|
||||||
|
#
|
||||||
|
# Any new source files that you add to the application should be added here.
|
||||||
|
add_executable(${BINARY_NAME}
|
||||||
|
"main.cc"
|
||||||
|
"my_application.cc"
|
||||||
|
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply the standard set of build settings. This can be removed for applications
|
||||||
|
# that need different build settings.
|
||||||
|
apply_standard_settings(${BINARY_NAME})
|
||||||
|
|
||||||
|
# Add dependency libraries. Add any application-specific dependencies here.
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||||
|
|
||||||
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
|
|
||||||
|
# Only the install-generated bundle's copy of the executable will launch
|
||||||
|
# correctly, since the resources must in the right relative locations. To avoid
|
||||||
|
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||||
|
# the default top-level location.
|
||||||
|
set_target_properties(${BINARY_NAME}
|
||||||
|
PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
|
# them to the application.
|
||||||
|
include(flutter/generated_plugins.cmake)
|
||||||
|
|
||||||
|
|
||||||
|
# === Installation ===
|
||||||
|
# By default, "installing" just makes a relocatable bundle in the build
|
||||||
|
# directory.
|
||||||
|
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Start with a clean build bundle directory every time.
|
||||||
|
install(CODE "
|
||||||
|
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||||
|
" COMPONENT Runtime)
|
||||||
|
|
||||||
|
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||||
|
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
|
||||||
|
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||||
|
install(FILES "${bundled_library}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
endforeach(bundled_library)
|
||||||
|
|
||||||
|
# Copy the native assets provided by the build.dart from all packages.
|
||||||
|
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
|
||||||
|
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||||
|
# from a previous install.
|
||||||
|
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||||
|
install(CODE "
|
||||||
|
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||||
|
" COMPONENT Runtime)
|
||||||
|
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
|
# Install the AOT library on non-Debug builds only.
|
||||||
|
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
|
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
endif()
|
88
frontend/linux/flutter/CMakeLists.txt
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# This file controls Flutter-level build steps. It should not be edited.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||||
|
|
||||||
|
# Configuration provided via flutter tool.
|
||||||
|
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||||
|
|
||||||
|
# TODO: Move the rest of this into files in ephemeral. See
|
||||||
|
# https://github.com/flutter/flutter/issues/57146.
|
||||||
|
|
||||||
|
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
||||||
|
# which isn't available in 3.10.
|
||||||
|
function(list_prepend LIST_NAME PREFIX)
|
||||||
|
set(NEW_LIST "")
|
||||||
|
foreach(element ${${LIST_NAME}})
|
||||||
|
list(APPEND NEW_LIST "${PREFIX}${element}")
|
||||||
|
endforeach(element)
|
||||||
|
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# === Flutter Library ===
|
||||||
|
# System-level dependencies.
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
|
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||||
|
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||||
|
|
||||||
|
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
||||||
|
|
||||||
|
# Published to parent scope for install step.
|
||||||
|
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||||
|
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||||
|
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||||
|
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||||
|
"fl_basic_message_channel.h"
|
||||||
|
"fl_binary_codec.h"
|
||||||
|
"fl_binary_messenger.h"
|
||||||
|
"fl_dart_project.h"
|
||||||
|
"fl_engine.h"
|
||||||
|
"fl_json_message_codec.h"
|
||||||
|
"fl_json_method_codec.h"
|
||||||
|
"fl_message_codec.h"
|
||||||
|
"fl_method_call.h"
|
||||||
|
"fl_method_channel.h"
|
||||||
|
"fl_method_codec.h"
|
||||||
|
"fl_method_response.h"
|
||||||
|
"fl_plugin_registrar.h"
|
||||||
|
"fl_plugin_registry.h"
|
||||||
|
"fl_standard_message_codec.h"
|
||||||
|
"fl_standard_method_codec.h"
|
||||||
|
"fl_string_codec.h"
|
||||||
|
"fl_value.h"
|
||||||
|
"fl_view.h"
|
||||||
|
"flutter_linux.h"
|
||||||
|
)
|
||||||
|
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
||||||
|
add_library(flutter INTERFACE)
|
||||||
|
target_include_directories(flutter INTERFACE
|
||||||
|
"${EPHEMERAL_DIR}"
|
||||||
|
)
|
||||||
|
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
||||||
|
target_link_libraries(flutter INTERFACE
|
||||||
|
PkgConfig::GTK
|
||||||
|
PkgConfig::GLIB
|
||||||
|
PkgConfig::GIO
|
||||||
|
)
|
||||||
|
add_dependencies(flutter flutter_assemble)
|
||||||
|
|
||||||
|
# === Flutter tool backend ===
|
||||||
|
# _phony_ is a non-existent file to force this command to run every time,
|
||||||
|
# since currently there's no way to get a full input/output list from the
|
||||||
|
# flutter tool.
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env
|
||||||
|
${FLUTTER_TOOL_ENVIRONMENT}
|
||||||
|
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
||||||
|
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
add_custom_target(flutter_assemble DEPENDS
|
||||||
|
"${FLUTTER_LIBRARY}"
|
||||||
|
${FLUTTER_LIBRARY_HEADERS}
|
||||||
|
)
|
11
frontend/linux/flutter/generated_plugin_registrant.cc
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
}
|
15
frontend/linux/flutter/generated_plugin_registrant.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
#define GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
|
||||||
|
// Registers Flutter plugins.
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry);
|
||||||
|
|
||||||
|
#endif // GENERATED_PLUGIN_REGISTRANT_
|
23
frontend/linux/flutter/generated_plugins.cmake
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
||||||
|
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||||
|
endforeach(plugin)
|
||||||
|
|
||||||
|
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||||
|
endforeach(ffi_plugin)
|
6
frontend/linux/main.cc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "my_application.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
g_autoptr(MyApplication) app = my_application_new();
|
||||||
|
return g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
|
}
|
104
frontend/linux/my_application.cc
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include "my_application.h"
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
struct _MyApplication {
|
||||||
|
GtkApplication parent_instance;
|
||||||
|
char** dart_entrypoint_arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
||||||
|
|
||||||
|
// Implements GApplication::activate.
|
||||||
|
static void my_application_activate(GApplication* application) {
|
||||||
|
MyApplication* self = MY_APPLICATION(application);
|
||||||
|
GtkWindow* window =
|
||||||
|
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||||
|
|
||||||
|
// Use a header bar when running in GNOME as this is the common style used
|
||||||
|
// by applications and is the setup most users will be using (e.g. Ubuntu
|
||||||
|
// desktop).
|
||||||
|
// If running on X and not using GNOME then just use a traditional title bar
|
||||||
|
// in case the window manager does more exotic layout, e.g. tiling.
|
||||||
|
// If running on Wayland assume the header bar will work (may need changing
|
||||||
|
// if future cases occur).
|
||||||
|
gboolean use_header_bar = TRUE;
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
GdkScreen* screen = gtk_window_get_screen(window);
|
||||||
|
if (GDK_IS_X11_SCREEN(screen)) {
|
||||||
|
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||||
|
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||||
|
use_header_bar = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (use_header_bar) {
|
||||||
|
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||||
|
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||||
|
gtk_header_bar_set_title(header_bar, "aurcache");
|
||||||
|
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||||
|
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||||
|
} else {
|
||||||
|
gtk_window_set_title(window, "aurcache");
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
gtk_widget_show(GTK_WIDGET(window));
|
||||||
|
|
||||||
|
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||||
|
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
||||||
|
|
||||||
|
FlView* view = fl_view_new(project);
|
||||||
|
gtk_widget_show(GTK_WIDGET(view));
|
||||||
|
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||||
|
|
||||||
|
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||||
|
|
||||||
|
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GApplication::local_command_line.
|
||||||
|
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
|
||||||
|
MyApplication* self = MY_APPLICATION(application);
|
||||||
|
// Strip out the first argument as it is the binary name.
|
||||||
|
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
||||||
|
|
||||||
|
g_autoptr(GError) error = nullptr;
|
||||||
|
if (!g_application_register(application, nullptr, &error)) {
|
||||||
|
g_warning("Failed to register: %s", error->message);
|
||||||
|
*exit_status = 1;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_application_activate(application);
|
||||||
|
*exit_status = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GObject::dispose.
|
||||||
|
static void my_application_dispose(GObject* object) {
|
||||||
|
MyApplication* self = MY_APPLICATION(object);
|
||||||
|
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
||||||
|
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_application_class_init(MyApplicationClass* klass) {
|
||||||
|
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
||||||
|
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
|
||||||
|
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_application_init(MyApplication* self) {}
|
||||||
|
|
||||||
|
MyApplication* my_application_new() {
|
||||||
|
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||||
|
"application-id", APPLICATION_ID,
|
||||||
|
"flags", G_APPLICATION_NON_UNIQUE,
|
||||||
|
nullptr));
|
||||||
|
}
|
18
frontend/linux/my_application.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef FLUTTER_MY_APPLICATION_H_
|
||||||
|
#define FLUTTER_MY_APPLICATION_H_
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
|
||||||
|
GtkApplication)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* my_application_new:
|
||||||
|
*
|
||||||
|
* Creates a new Flutter-based application.
|
||||||
|
*
|
||||||
|
* Returns: a new #MyApplication.
|
||||||
|
*/
|
||||||
|
MyApplication* my_application_new();
|
||||||
|
|
||||||
|
#endif // FLUTTER_MY_APPLICATION_H_
|
397
frontend/pubspec.lock
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
# Generated by pub
|
||||||
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
|
packages:
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: async
|
||||||
|
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.11.0"
|
||||||
|
boolean_selector:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: boolean_selector
|
||||||
|
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
characters:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: characters
|
||||||
|
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
clock:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: clock
|
||||||
|
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
collection:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: collection
|
||||||
|
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.18.0"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.3"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.6"
|
||||||
|
equatable:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: equatable
|
||||||
|
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.5"
|
||||||
|
fake_async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fake_async
|
||||||
|
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.1"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
fl_chart:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: fl_chart
|
||||||
|
sha256: fe6fec7d85975a99c73b9515a69a6e291364accfa0e4a5b3ce6de814d74b9a1c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.66.0"
|
||||||
|
flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
flutter_lints:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_lints
|
||||||
|
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
|
flutter_svg:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_svg
|
||||||
|
sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.9"
|
||||||
|
flutter_test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
google_fonts:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_fonts
|
||||||
|
sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.0"
|
||||||
|
http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.2"
|
||||||
|
lints:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: lints
|
||||||
|
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
matcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: matcher
|
||||||
|
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.16"
|
||||||
|
material_color_utilities:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: material_color_utilities
|
||||||
|
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
|
meta:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: meta
|
||||||
|
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.10.0"
|
||||||
|
path:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path
|
||||||
|
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.8.3"
|
||||||
|
path_parsing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_parsing
|
||||||
|
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
path_provider:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider
|
||||||
|
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
path_provider_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_android
|
||||||
|
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
|
path_provider_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_foundation
|
||||||
|
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.1"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.2"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
|
plugin_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: plugin_platform_interface
|
||||||
|
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.7"
|
||||||
|
sky_engine:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.99"
|
||||||
|
source_span:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_span
|
||||||
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.10.0"
|
||||||
|
stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stack_trace
|
||||||
|
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.11.1"
|
||||||
|
stream_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_channel
|
||||||
|
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
string_scanner:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: string_scanner
|
||||||
|
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
term_glyph:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: term_glyph
|
||||||
|
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.1"
|
||||||
|
test_api:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_api
|
||||||
|
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.1"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.2"
|
||||||
|
vector_graphics:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_graphics
|
||||||
|
sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.9+1"
|
||||||
|
vector_graphics_codec:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_graphics_codec
|
||||||
|
sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.9+1"
|
||||||
|
vector_graphics_compiler:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_graphics_compiler
|
||||||
|
sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.9+1"
|
||||||
|
vector_math:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_math
|
||||||
|
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.4"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.0"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.1"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.5.0"
|
||||||
|
sdks:
|
||||||
|
dart: ">=3.2.3 <4.0.0"
|
||||||
|
flutter: ">=3.16.0"
|
99
frontend/pubspec.yaml
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
name: aurcache
|
||||||
|
description: "A new Flutter project."
|
||||||
|
# The following line prevents the package from being accidentally published to
|
||||||
|
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||||
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
|
# The following defines the version and build number for your application.
|
||||||
|
# A version number is three numbers separated by dots, like 1.2.43
|
||||||
|
# followed by an optional build number separated by a +.
|
||||||
|
# Both the version and the builder number may be overridden in flutter
|
||||||
|
# build by specifying --build-name and --build-number, respectively.
|
||||||
|
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||||
|
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||||
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
|
||||||
|
# Read more about iOS versioning at
|
||||||
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
|
version: 1.0.0+1
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=3.2.3 <4.0.0'
|
||||||
|
|
||||||
|
# Dependencies specify other packages that your package needs in order to work.
|
||||||
|
# To automatically upgrade your package dependencies to the latest versions
|
||||||
|
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||||
|
# dependencies can be manually updated by changing the version numbers below to
|
||||||
|
# the latest version available on pub.dev. To see which dependencies have newer
|
||||||
|
# versions available, run `flutter pub outdated`.
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
|
# The following adds the Cupertino Icons font to your application.
|
||||||
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
cupertino_icons: ^1.0.2
|
||||||
|
fl_chart: ^0.66.0
|
||||||
|
# flutter_icons:
|
||||||
|
# git:
|
||||||
|
# url: https://github.com/DaveatCor/flutter_icons_fork.git
|
||||||
|
# branch: master
|
||||||
|
flutter_svg: ^2.0.9
|
||||||
|
google_fonts: ^6.1.0
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
# The "flutter_lints" package below contains a set of recommended lints to
|
||||||
|
# encourage good coding practices. The lint set provided by the package is
|
||||||
|
# activated in the `analysis_options.yaml` file located at the root of your
|
||||||
|
# package. See that file for information about deactivating specific lint
|
||||||
|
# rules and activating additional ones.
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
|
|
||||||
|
# For information on the generic Dart part of this file, see the
|
||||||
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
# The following section is specific to Flutter packages.
|
||||||
|
flutter:
|
||||||
|
|
||||||
|
# The following line ensures that the Material Icons font is
|
||||||
|
# included with your application, so that you can use the icons in
|
||||||
|
# the material Icons class.
|
||||||
|
uses-material-design: true
|
||||||
|
assets:
|
||||||
|
- assets/icons/
|
||||||
|
|
||||||
|
# To add assets to your application, add an assets section, like this:
|
||||||
|
# assets:
|
||||||
|
# - images/a_dot_burr.jpeg
|
||||||
|
# - images/a_dot_ham.jpeg
|
||||||
|
|
||||||
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
|
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||||
|
|
||||||
|
# For details regarding adding assets from package dependencies, see
|
||||||
|
# https://flutter.dev/assets-and-images/#from-packages
|
||||||
|
|
||||||
|
# To add custom fonts to your application, add a fonts section here,
|
||||||
|
# in this "flutter" section. Each entry in this list should have a
|
||||||
|
# "family" key with the font family name, and a "fonts" key with a
|
||||||
|
# list giving the asset and other descriptors for the font. For
|
||||||
|
# example:
|
||||||
|
# fonts:
|
||||||
|
# - family: Schyler
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/Schyler-Regular.ttf
|
||||||
|
# - asset: fonts/Schyler-Italic.ttf
|
||||||
|
# style: italic
|
||||||
|
# - family: Trajan Pro
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/TrajanPro.ttf
|
||||||
|
# - asset: fonts/TrajanPro_Bold.ttf
|
||||||
|
# weight: 700
|
||||||
|
#
|
||||||
|
# For details regarding fonts from package dependencies,
|
||||||
|
# see https://flutter.dev/custom-fonts/#from-packages
|
30
frontend/test/widget_test.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// This is a basic Flutter widget test.
|
||||||
|
//
|
||||||
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
|
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||||
|
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||||
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import 'package:aurcache/main.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
|
// Build our app and trigger a frame.
|
||||||
|
await tester.pumpWidget(const MyApp());
|
||||||
|
|
||||||
|
// Verify that our counter starts at 0.
|
||||||
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
expect(find.text('1'), findsNothing);
|
||||||
|
|
||||||
|
// Tap the '+' icon and trigger a frame.
|
||||||
|
await tester.tap(find.byIcon(Icons.add));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
// Verify that our counter has incremented.
|
||||||
|
expect(find.text('0'), findsNothing);
|
||||||
|
expect(find.text('1'), findsOneWidget);
|
||||||
|
});
|
||||||
|
}
|
BIN
frontend/web/favicon.png
Normal file
After Width: | Height: | Size: 917 B |
BIN
frontend/web/icons/Icon-192.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
frontend/web/icons/Icon-512.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
frontend/web/icons/Icon-maskable-192.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
frontend/web/icons/Icon-maskable-512.png
Normal file
After Width: | Height: | Size: 20 KiB |
59
frontend/web/index.html
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!--
|
||||||
|
If you are serving your web app in a path other than the root, change the
|
||||||
|
href value below to reflect the base path you are serving from.
|
||||||
|
|
||||||
|
The path provided below has to start and end with a slash "/" in order for
|
||||||
|
it to work correctly.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||||
|
|
||||||
|
This is a placeholder for base href that will be replaced by the value of
|
||||||
|
the `--base-href` argument provided to `flutter build`.
|
||||||
|
-->
|
||||||
|
<base href="$FLUTTER_BASE_HREF">
|
||||||
|
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||||
|
<meta name="description" content="A new Flutter project.">
|
||||||
|
|
||||||
|
<!-- iOS meta tags & icons -->
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
|
<meta name="apple-mobile-web-app-title" content="aurcache">
|
||||||
|
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||||
|
|
||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||||
|
|
||||||
|
<title>aurcache</title>
|
||||||
|
<link rel="manifest" href="manifest.json">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// The value below is injected by flutter build, do not touch.
|
||||||
|
const serviceWorkerVersion = null;
|
||||||
|
</script>
|
||||||
|
<!-- This script adds the flutter initialization JS code -->
|
||||||
|
<script src="flutter.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
window.addEventListener('load', function(ev) {
|
||||||
|
// Download main.dart.js
|
||||||
|
_flutter.loader.loadEntrypoint({
|
||||||
|
serviceWorker: {
|
||||||
|
serviceWorkerVersion: serviceWorkerVersion,
|
||||||
|
},
|
||||||
|
onEntrypointLoaded: function(engineInitializer) {
|
||||||
|
engineInitializer.initializeEngine().then(function(appRunner) {
|
||||||
|
appRunner.runApp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
35
frontend/web/manifest.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "aurcache",
|
||||||
|
"short_name": "aurcache",
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#0175C2",
|
||||||
|
"theme_color": "#0175C2",
|
||||||
|
"description": "A new Flutter project.",
|
||||||
|
"orientation": "portrait-primary",
|
||||||
|
"prefer_related_applications": false,
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "icons/Icon-192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "icons/Icon-512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "icons/Icon-maskable-192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "icons/Icon-maskable-512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|