mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-04-02 17:45:28 +00:00
reorganize history memory model
This commit is contained in:
parent
6526ca85d8
commit
268af30830
14 changed files with 172 additions and 218 deletions
|
|
@ -36,11 +36,6 @@ impl Bookmark {
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
|
||||||
pub fn activate(&self) {
|
|
||||||
self.simple_action.activate(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
||||||
/// * set `DEFAULT_STATE` on `None`
|
/// * set `DEFAULT_STATE` on `None`
|
||||||
pub fn change_state(&self, state: Option<i32>) {
|
pub fn change_state(&self, state: Option<i32>) {
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,6 @@ impl HistoryBack {
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
|
||||||
pub fn activate(&self) {
|
|
||||||
self.simple_action.activate(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
||||||
/// * set `DEFAULT_STATE` on `None`
|
/// * set `DEFAULT_STATE` on `None`
|
||||||
pub fn change_state(&self, state: Option<i32>) {
|
pub fn change_state(&self, state: Option<i32>) {
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,6 @@ impl HistoryForward {
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
|
||||||
pub fn activate(&self) {
|
|
||||||
self.simple_action.activate(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
||||||
/// * set `DEFAULT_STATE` on `None`
|
/// * set `DEFAULT_STATE` on `None`
|
||||||
pub fn change_state(&self, state: Option<i32>) {
|
pub fn change_state(&self, state: Option<i32>) {
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,6 @@ impl Home {
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
|
||||||
pub fn activate(&self) {
|
|
||||||
self.simple_action.activate(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
/// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html)
|
||||||
/// * set `DEFAULT_STATE` on `None`
|
/// * set `DEFAULT_STATE` on `None`
|
||||||
pub fn change_state(&self, state: Option<i32>) {
|
pub fn change_state(&self, state: Option<i32>) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{BrowserAction, Profile, WindowAction};
|
use super::{BrowserAction, Profile, WindowAction};
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gio::{self},
|
gio::{self},
|
||||||
glib::{GString, Uri},
|
glib::{GString, Uri, UriFlags},
|
||||||
prelude::{ActionExt, ToVariant},
|
prelude::{ActionExt, ToVariant},
|
||||||
Align, MenuButton,
|
Align, MenuButton,
|
||||||
};
|
};
|
||||||
|
|
@ -220,14 +220,13 @@ impl Menu for MenuButton {
|
||||||
|
|
||||||
// Recently closed history
|
// Recently closed history
|
||||||
main_history_tab.remove_all();
|
main_history_tab.remove_all();
|
||||||
for item in profile.history.memory.tab.recent() {
|
for history in profile.history.recently_closed(None) {
|
||||||
let item_request = item.page.navigation.request(); // @TODO restore entire `Item`
|
let menu_item = gio::MenuItem::new(Some(&ellipsize(&history.request, LABEL_MAX_LENGTH)), None);
|
||||||
let menu_item = gio::MenuItem::new(Some(&ellipsize(&item_request, LABEL_MAX_LENGTH)), None);
|
|
||||||
menu_item.set_action_and_target_value(Some(&format!(
|
menu_item.set_action_and_target_value(Some(&format!(
|
||||||
"{}.{}",
|
"{}.{}",
|
||||||
window_action.id,
|
window_action.id,
|
||||||
window_action.load.simple_action.name()
|
window_action.load.simple_action.name()
|
||||||
)), Some(&item_request.to_variant()));
|
)), Some(&history.request.to_variant()));
|
||||||
|
|
||||||
main_history_tab.append_item(&menu_item);
|
main_history_tab.append_item(&menu_item);
|
||||||
} // @TODO `menu_item`
|
} // @TODO `menu_item`
|
||||||
|
|
@ -238,11 +237,14 @@ impl Menu for MenuButton {
|
||||||
main_history_request.remove_all();
|
main_history_request.remove_all();
|
||||||
|
|
||||||
let mut list: IndexMap<GString, Vec<Uri>> = IndexMap::new();
|
let mut list: IndexMap<GString, Vec<Uri>> = IndexMap::new();
|
||||||
for uri in profile.history.memory.request.recent() {
|
for history in profile.history.recently_opened(None) {
|
||||||
list.entry(match uri.host() {
|
match Uri::parse(&history.request, UriFlags::NONE) {
|
||||||
|
Ok(uri) => list.entry(match uri.host() {
|
||||||
Some(host) => host,
|
Some(host) => host,
|
||||||
None => uri.to_str(),
|
None => uri.to_str(),
|
||||||
}).or_default().push(uri);
|
}).or_default().push(uri),
|
||||||
|
Err(_) => continue // @TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (group, items) in list {
|
for (group, items) in list {
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,7 @@ use crate::Profile;
|
||||||
use action::Action;
|
use action::Action;
|
||||||
use adw::{TabPage, TabView};
|
use adw::{TabPage, TabView};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gtk::{
|
use gtk::{gio::Icon, glib::Propagation, prelude::ActionExt, Box, Orientation};
|
||||||
gio::Icon,
|
|
||||||
glib::{DateTime, Propagation},
|
|
||||||
prelude::ActionExt,
|
|
||||||
Box, Orientation,
|
|
||||||
};
|
|
||||||
pub use item::Item;
|
pub use item::Item;
|
||||||
use menu::Menu;
|
use menu::Menu;
|
||||||
use sourceview::prelude::IsA;
|
use sourceview::prelude::IsA;
|
||||||
|
|
@ -86,11 +81,7 @@ impl Tab {
|
||||||
// keep removed `Item` reference in the memory (to reopen from the main menu)
|
// keep removed `Item` reference in the memory (to reopen from the main menu)
|
||||||
// * skip item with blank request
|
// * skip item with blank request
|
||||||
if !item.page.navigation.request().is_empty() {
|
if !item.page.navigation.request().is_empty() {
|
||||||
profile
|
profile.history.close(&item.page.navigation.request());
|
||||||
.history
|
|
||||||
.memory
|
|
||||||
.tab
|
|
||||||
.add(item, DateTime::now_local().unwrap().to_unix());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// reassign global actions to active tab
|
// reassign global actions to active tab
|
||||||
|
|
|
||||||
|
|
@ -63,13 +63,13 @@ impl Client {
|
||||||
Ok(uri) => match uri.scheme().as_str() {
|
Ok(uri) => match uri.scheme().as_str() {
|
||||||
"file" => {
|
"file" => {
|
||||||
if is_snap_history {
|
if is_snap_history {
|
||||||
snap_history(&page, Some(&uri));
|
snap_history(&page);
|
||||||
}
|
}
|
||||||
driver.file.handle(uri, feature, cancellable)
|
driver.file.handle(uri, feature, cancellable)
|
||||||
}
|
}
|
||||||
"gemini" | "titan" => {
|
"gemini" | "titan" => {
|
||||||
if is_snap_history {
|
if is_snap_history {
|
||||||
snap_history(&page, Some(&uri));
|
snap_history(&page);
|
||||||
}
|
}
|
||||||
driver.gemini.handle(uri, feature, cancellable)
|
driver.gemini.handle(uri, feature, cancellable)
|
||||||
}
|
}
|
||||||
|
|
@ -201,23 +201,9 @@ fn search(profile: &Profile, query: &str) -> Uri {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make new history record in related components
|
/// Make new history record in related components
|
||||||
/// * optional [Uri](https://docs.gtk.org/glib/struct.Uri.html) reference wanted only for performance reasons, to not parse it twice
|
fn snap_history(page: &Page) {
|
||||||
fn snap_history(page: &Page, uri: Option<&Uri>) {
|
page.item_action
|
||||||
let request = page.navigation.request();
|
.history
|
||||||
|
.add(page.navigation.request(), true);
|
||||||
// Add new record into the global memory index (used in global menu)
|
page.profile.history.open(page.navigation.request())
|
||||||
// * if the `Uri` is `None`, try parse it from `request`
|
|
||||||
match uri {
|
|
||||||
Some(uri) => page.profile.history.memory.request.set(uri.clone()),
|
|
||||||
None => {
|
|
||||||
// this case especially useful for some routes that contain redirects
|
|
||||||
// maybe some parental optimization wanted @TODO
|
|
||||||
if let Some(uri) = page.navigation.uri() {
|
|
||||||
page.profile.history.memory.request.set(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new record into the page navigation history
|
|
||||||
page.item_action.history.add(request, true)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,10 +121,8 @@ impl Page {
|
||||||
self.set_needs_attention(record.is_needs_attention);
|
self.set_needs_attention(record.is_needs_attention);
|
||||||
// Restore child components
|
// Restore child components
|
||||||
self.navigation.restore(transaction, &record.id)?;
|
self.navigation.restore(transaction, &record.id)?;
|
||||||
// Make initial page history snap using `navigation` values restored
|
// Make initial page history snap
|
||||||
if let Some(uri) = self.navigation.uri() {
|
self.profile.history.open(self.navigation.request());
|
||||||
self.profile.history.memory.request.set(uri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -137,10 +137,6 @@ impl Navigation {
|
||||||
self.request.text()
|
self.request.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uri(&self) -> Option<Uri> {
|
|
||||||
self.request.uri()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn home(&self) -> Option<Uri> {
|
pub fn home(&self) -> Option<Uri> {
|
||||||
self.request.home()
|
self.request.home()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
// mod database;
|
// mod database;
|
||||||
|
mod item;
|
||||||
mod memory;
|
mod memory;
|
||||||
|
|
||||||
|
use gtk::glib::GString;
|
||||||
|
use item::Item;
|
||||||
use memory::Memory;
|
use memory::Memory;
|
||||||
|
|
||||||
use sqlite::Connection;
|
use sqlite::Connection;
|
||||||
use std::{rc::Rc, sync::RwLock};
|
use std::{cell::RefCell, rc::Rc, sync::RwLock};
|
||||||
|
|
||||||
pub struct History {
|
pub struct History {
|
||||||
pub memory: Rc<Memory>, // fast search index
|
memory: RefCell<Memory>, // fast search index
|
||||||
}
|
}
|
||||||
|
|
||||||
impl History {
|
impl History {
|
||||||
|
|
@ -16,9 +18,36 @@ impl History {
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn build(_connection: &Rc<RwLock<Connection>>, _profile_id: &Rc<i64>) -> Self {
|
pub fn build(_connection: &Rc<RwLock<Connection>>, _profile_id: &Rc<i64>) -> Self {
|
||||||
// Init children components
|
// Init children components
|
||||||
let memory = Rc::new(Memory::new());
|
let memory = RefCell::new(Memory::new());
|
||||||
|
|
||||||
// Return new `Self`
|
// Return new `Self`
|
||||||
Self { memory }
|
Self { memory }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
|
||||||
|
/// Create new history record
|
||||||
|
pub fn open(&self, request: GString) {
|
||||||
|
let mut memory = self.memory.borrow_mut();
|
||||||
|
if !memory.open(&request) {
|
||||||
|
memory.add(Item::create(0, request)) // @TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close existing history record
|
||||||
|
pub fn close(&self, request: &str) {
|
||||||
|
self.memory.borrow_mut().close(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
|
||||||
|
/// Get recently `opened` Items vector from the memory index, sorted by ASC
|
||||||
|
pub fn recently_opened(&self, limit: Option<usize>) -> Vec<Item> {
|
||||||
|
self.memory.borrow().recently_opened(limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get recently `closed` Items vector from the memory index, sorted by ASC
|
||||||
|
pub fn recently_closed(&self, limit: Option<usize>) -> Vec<Item> {
|
||||||
|
self.memory.borrow().recently_closed(limit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
src/profile/history/item.rs
Normal file
40
src/profile/history/item.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
use gtk::glib::{DateTime, GString};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Item {
|
||||||
|
pub id: i64,
|
||||||
|
pub request: GString,
|
||||||
|
pub created: DateTime,
|
||||||
|
pub opened: DateTime,
|
||||||
|
pub closed: Option<DateTime>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Item {
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
pub fn create(id: i64, request: GString) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
request,
|
||||||
|
created: now(),
|
||||||
|
opened: now(),
|
||||||
|
closed: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
|
||||||
|
pub fn open(&mut self) {
|
||||||
|
self.opened = now()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(&mut self) {
|
||||||
|
self.closed = Some(now())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tools
|
||||||
|
|
||||||
|
fn now() -> DateTime {
|
||||||
|
DateTime::now_local().unwrap()
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,81 @@
|
||||||
mod request;
|
use super::Item;
|
||||||
mod tab;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use request::Request;
|
|
||||||
use tab::Tab;
|
|
||||||
|
|
||||||
/// Reduce disk usage by cache Bookmarks index in memory
|
/// Reduce disk usage by cache Bookmarks index in memory
|
||||||
pub struct Memory {
|
pub struct Memory(Vec<Item>);
|
||||||
pub request: Request,
|
|
||||||
pub tab: Tab,
|
impl Memory {
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
/// Create new `Self`
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
|
||||||
|
pub fn add(&mut self, item: Item) {
|
||||||
|
self.0.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update `opened` time for given `request`
|
||||||
|
/// * return `false` if the `request` not found in memory index
|
||||||
|
pub fn open(&mut self, request: &str) -> bool {
|
||||||
|
for record in &mut self.0 {
|
||||||
|
if record.request == request {
|
||||||
|
record.open();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update `closed` time for given `request`
|
||||||
|
pub fn close(&mut self, request: &str) {
|
||||||
|
for record in &mut self.0 {
|
||||||
|
if record.request == request {
|
||||||
|
record.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
|
||||||
|
/// Get recent Items vector sorted by `closed` ASC
|
||||||
|
pub fn recently_closed(&self, limit: Option<usize>) -> Vec<Item> {
|
||||||
|
let mut recent: Vec<Item> = Vec::new();
|
||||||
|
for (i, item) in self
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.filter(|x| x.closed.is_some())
|
||||||
|
.sorted_by(|a, b| Ord::cmp(&a.closed, &b.closed))
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if limit.is_some_and(|l| i > l) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
recent.push(item.clone())
|
||||||
|
}
|
||||||
|
recent
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get recent Items vector sorted by `opened` ASC
|
||||||
|
pub fn recently_opened(&self, limit: Option<usize>) -> Vec<Item> {
|
||||||
|
let mut recent: Vec<Item> = Vec::new();
|
||||||
|
for (i, item) in self
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.sorted_by(|a, b| Ord::cmp(&a.opened, &b.opened))
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if limit.is_some_and(|l| i > l) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
recent.push(item.clone())
|
||||||
|
}
|
||||||
|
recent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Memory {
|
impl Default for Memory {
|
||||||
|
|
@ -15,15 +83,3 @@ impl Default for Memory {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memory {
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
/// Create new `Self`
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
request: Request::new(),
|
|
||||||
tab: Tab::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
use gtk::glib::{DateTime, GString, Uri};
|
|
||||||
use itertools::Itertools;
|
|
||||||
use std::{cell::RefCell, collections::HashMap};
|
|
||||||
|
|
||||||
pub struct Value {
|
|
||||||
pub unix_timestamp: i64,
|
|
||||||
pub uri: Uri,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Recent request history
|
|
||||||
pub struct Request {
|
|
||||||
index: RefCell<HashMap<GString, Value>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Request {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Request {
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
/// Create new `Self`
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
index: RefCell::new(HashMap::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
|
|
||||||
/// Add new record with `request` as key and `unix_timestamp` as value
|
|
||||||
/// * replace with new value if `request` already exists
|
|
||||||
pub fn set(&self, uri: Uri) {
|
|
||||||
self.index.borrow_mut().insert(
|
|
||||||
uri.to_str(),
|
|
||||||
Value {
|
|
||||||
unix_timestamp: DateTime::now_local().unwrap().to_unix(),
|
|
||||||
uri,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get recent records vector
|
|
||||||
/// * sorted by `unix_timestamp` DESC
|
|
||||||
pub fn recent(&self) -> Vec<Uri> {
|
|
||||||
let mut recent: Vec<Uri> = Vec::new();
|
|
||||||
for (_, value) in self
|
|
||||||
.index
|
|
||||||
.borrow()
|
|
||||||
.iter()
|
|
||||||
.sorted_by(|a, b| Ord::cmp(&b.1.unix_timestamp, &a.1.unix_timestamp))
|
|
||||||
{
|
|
||||||
recent.push(value.uri.clone())
|
|
||||||
}
|
|
||||||
recent
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get records total
|
|
||||||
pub fn total(&self) -> usize {
|
|
||||||
self.index.borrow().len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
use crate::app::browser::window::tab::Item;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
|
||||||
|
|
||||||
pub struct Record {
|
|
||||||
pub item: Rc<Item>,
|
|
||||||
pub unix_timestamp: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Recently closed tabs index
|
|
||||||
pub struct Tab {
|
|
||||||
index: RefCell<Vec<Record>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Tab {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Tab {
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
/// Create new `Self`
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
index: RefCell::new(Vec::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
|
|
||||||
/// Add new record
|
|
||||||
/// * replace with new one if the record already exist
|
|
||||||
pub fn add(&self, item: Rc<Item>, unix_timestamp: i64) {
|
|
||||||
self.index.borrow_mut().push(Record {
|
|
||||||
item,
|
|
||||||
unix_timestamp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get recent `Item` vector sorted by `unix_timestamp` DESC
|
|
||||||
pub fn recent(&self) -> Vec<Rc<Item>> {
|
|
||||||
let mut recent: Vec<Rc<Item>> = Vec::new();
|
|
||||||
for record in self
|
|
||||||
.index
|
|
||||||
.borrow()
|
|
||||||
.iter()
|
|
||||||
.sorted_by(|a, b| Ord::cmp(&b.unix_timestamp, &a.unix_timestamp))
|
|
||||||
{
|
|
||||||
recent.push(record.item.clone())
|
|
||||||
}
|
|
||||||
recent
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get records total
|
|
||||||
pub fn total(&self) -> usize {
|
|
||||||
self.index.borrow().len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue