Skip to content

Commit

Permalink
Refactor native part
Browse files Browse the repository at this point in the history
  • Loading branch information
Yesterday17 committed Aug 29, 2023
1 parent be9a569 commit 33402d7
Show file tree
Hide file tree
Showing 51 changed files with 2,763 additions and 4,252 deletions.
6 changes: 6 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"recommendations": [
"rust-lang.rust-analyzer",
"dart-code.flutter"
]
}
27 changes: 5 additions & 22 deletions annix/.flutter_rust_bridge.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,16 @@
rust_input:
- src/repo/api.rs
- src/preferences/api.rs
- src/store/api.rs
- src/network/api.rs
- src/api.rs
rust_output:
- src/repo/generated.rs
- src/preferences/generated.rs
- src/store/generated.rs
- src/network/generated.rs
- src/bridge_generated.rs

class_name:
- ApiRepository
- ApiPreferenceStore
- ApiStore
- ApiNetwork
dart_output:
- ../lib/bridge/generated_repo.dart
- ../lib/bridge/generated_preferences.dart
- ../lib/bridge/generated_store.dart
- ../lib/bridge/generated_network.dart
- ../lib/bridge/bridge_generated.dart
c_output:
- ../ios/Runner/generated_repo.h
- ../ios/Runner/generated_preferences.h
- ../ios/Runner/generated_store.h
- ../ios/Runner/generated_network.h
- ../ios/Runner/bridge_generated.h
extra_c_output_path:
- ../macos/Runner/

# dart_decl_output: ../lib/bridge/definitions.dart
dart_decl_output: ../lib/bridge/bridge_definitions.dart
dart_format_line_length: 120
dart_enums_style: true
# dump: []
Expand Down
16 changes: 8 additions & 8 deletions annix/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use lib_flutter_rust_bridge_codegen::{
const RUST_INPUT: &str = "src/api.rs";

fn main() {
// init_logger("./logs/", true).unwrap();
// println!("cargo:rerun-if-changed={RUST_INPUT}");
init_logger("./logs/", true).unwrap();
println!("cargo:rerun-if-changed={RUST_INPUT}");

// let raw_opts = RawOpts::try_parse_args_or_yaml().unwrap();
// let configs = config_parse(raw_opts);
// let all_symbols = get_symbols_if_no_duplicates(&configs).unwrap();
let raw_opts = RawOpts::try_parse_args_or_yaml().unwrap();
let configs = config_parse(raw_opts);
let all_symbols = get_symbols_if_no_duplicates(&configs).unwrap();

// for config_index in 0..configs.len() {
// frb_codegen_multi(&configs, config_index, &all_symbols).unwrap();
// }
for config_index in 0..configs.len() {
frb_codegen_multi(&configs, config_index, &all_symbols).unwrap();
}
}
229 changes: 229 additions & 0 deletions annix/src/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
pub use anni_repo::{db::RepoDatabaseRead, prelude::JsonAlbum};
pub use flutter_rust_bridge::{RustOpaque, SyncReturn};
use once_cell::sync::Lazy;
pub use rusqlite::Connection;
pub use uuid::Uuid;

use std::sync::RwLock;
pub use std::{path::PathBuf, sync::Mutex};

pub enum NetworkStatus {
Online,
Offline,
}

impl NetworkStatus {
pub fn is_online(&self) -> bool {
match self {
NetworkStatus::Online => true,
NetworkStatus::Offline => false,
}
}
}

pub static NETWORK: Lazy<RwLock<NetworkStatus>> = Lazy::new(|| RwLock::new(NetworkStatus::Offline));

pub fn update_network_status(is_online: bool) {
let mut network = NETWORK.write().unwrap();
*network = if is_online {
NetworkStatus::Online
} else {
NetworkStatus::Offline
};
}

/// Preferences
use crate::dummy;

dummy!(Dummy1);

pub struct NativePreferenceStore {
pub conn: RustOpaque<Mutex<Dummy1<Connection>>>,
}

impl NativePreferenceStore {
pub fn new(root: String) -> SyncReturn<NativePreferenceStore> {
let db_path = PathBuf::from(&root).join("preference.db");
std::fs::create_dir_all(&root).unwrap();
let conn = Connection::open(db_path).unwrap();
conn.execute(
r#"
CREATE TABLE IF NOT EXISTS preferences(
key TEXT PRIMARY KEY ON CONFLICT REPLACE,
value TEXT NOT NULL
);
"#,
(),
)
.unwrap();

let conn = RustOpaque::new(Mutex::new(Dummy1(conn)));
SyncReturn(Self { conn })
}

pub fn get(&self, key: String) -> SyncReturn<Option<String>> {
let conn = self.conn.lock().unwrap();
let mut stmt = conn
.prepare("SELECT value FROM preferences WHERE key = ?")
.unwrap();
let mut rows = stmt.query(rusqlite::params![key]).unwrap();
let result = rows
.next()
.ok()
.and_then(|r| r)
.and_then(|row| row.get(0).ok());

SyncReturn(result)
}

pub fn set(&self, key: String, value: String) -> SyncReturn<()> {
self.conn
.lock()
.unwrap()
.execute(
"INSERT INTO preferences (key, value) VALUES (?, ?)",
rusqlite::params![key, value],
)
.unwrap();

SyncReturn(())
}

pub fn remove(&self, key: String) -> SyncReturn<()> {
self.conn
.lock()
.unwrap()
.execute(
"DELETE FROM preferences WHERE key = ?",
rusqlite::params![key],
)
.unwrap();

SyncReturn(())
}

pub fn remove_prefix(&self, prefix: String) -> SyncReturn<()> {
self.conn
.lock()
.unwrap()
.execute(
"DELETE FROM preferences WHERE key LIKE ?",
rusqlite::params![format!("{}%", prefix)],
)
.unwrap();

SyncReturn(())
}
}

/// Repo

pub struct LocalDb {
pub repo: RustOpaque<Mutex<RepoDatabaseRead>>,
}

pub struct TagItem {
pub name: String,
pub children: Vec<String>,
}

impl LocalDb {
pub fn new(path: String) -> LocalDb {
let repo = RepoDatabaseRead::new(path).unwrap();
let repo = RustOpaque::new(Mutex::new(repo));
Self { repo }
}

pub fn get_album(&self, album_id: uuid::Uuid) -> Option<String> {
let album = self.repo.lock().unwrap().read_album(album_id).unwrap();
album.map(|album| JsonAlbum::from(album).to_string())
}

pub fn get_albums_by_tag(&self, tag: String, recursive: bool) -> Vec<Uuid> {
let albums = self
.repo
.lock()
.unwrap()
.get_albums_by_tag(&tag, recursive)
.unwrap();
albums.into_iter().map(|album| album.album_id.0).collect()
}

pub fn get_tags(&self) -> Vec<TagItem> {
let albums = self.repo.lock().unwrap().get_tags_relationship().unwrap();
albums
.into_iter()
.map(|(_, tag)| TagItem {
name: tag.tag.to_string(),
children: tag
.children
.into_iter()
.map(|tag| tag.to_string())
.collect(),
})
.collect()
}
}

/// API
pub type LocalStoreConnection = Mutex<Connection>;

pub struct LocalStore {
pub conn: RustOpaque<LocalStoreConnection>,
}

impl LocalStore {
pub fn new(root: String) -> SyncReturn<LocalStore> {
let db_path = PathBuf::from(root).join("cache.db");
let conn = Connection::open(db_path).unwrap();
conn.execute(
r#"
CREATE TABLE IF NOT EXISTS store(
id INTEGER PRIMARY KEY,
category TEXT NOT NULL,
key TEXT NOT NULL,
value TEXT NOT NULL,
UNIQUE("category", "key", "value") ON CONFLICT REPLACE
);"#,
(),
)
.unwrap();

let conn = RustOpaque::new(Mutex::new(conn));
SyncReturn(Self { conn })
}

pub fn insert(&self, category: String, key: String, value: String) {
self.conn
.lock()
.unwrap()
.execute(
"INSERT INTO store (category, key, value) VALUES (?, ?, ?)",
rusqlite::params![category, key, value],
)
.unwrap();
}

pub fn get(&self, category: String, key: String) -> Option<String> {
let conn = self.conn.lock().unwrap();
let mut stmt = conn
.prepare("SELECT value FROM store WHERE category = ? AND key = ?")
.unwrap();
let mut rows = stmt.query(rusqlite::params![category, key]).unwrap();
rows.next()
.ok()
.and_then(|r| r)
.and_then(|row| row.get(0).ok())
}

pub fn clear(&self, category: Option<String>) {
self.conn
.lock()
.unwrap()
.execute(
"DELETE FROM store WHERE category = ?",
rusqlite::params![category],
)
.unwrap();
}
}
Loading

0 comments on commit 33402d7

Please sign in to comment.