11import AsyncStorage from '@react-native-async-storage/async-storage'
2- import { solNative } from 'lib/SolNative'
3- import { autorun , makeAutoObservable , runInAction , toJS } from 'mobx'
4- import { EmitterSubscription } from 'react-native'
5- import { IRootStore } from 'store'
6- import { Widget } from './ui.store'
2+ import { solNative } from 'lib/SolNative'
3+ import { autorun , makeAutoObservable , runInAction , toJS } from 'mobx'
4+ import { EmitterSubscription } from 'react-native'
5+ import { IRootStore } from 'store'
6+ import { Widget } from './ui.store'
77import MiniSearch from 'minisearch'
8- import { storage } from './storage'
9- import { captureException } from '@sentry/react-native'
8+ import { storage } from './storage'
9+ import { captureException } from '@sentry/react-native'
1010
1111const MAX_ITEMS = 1000
1212
@@ -20,27 +20,31 @@ export type PasteItem = {
2020 text : string
2121 url ?: string | null
2222 bundle ?: string | null
23+ datetime : number // Unix timestamp when copied
2324}
2425
2526let minisearch = new MiniSearch ( {
2627 fields : [ 'text' , 'bundle' ] ,
27- storeFields : [ 'text' , 'url' , 'bundle' ] ,
28+ storeFields : [ 'id' , ' text', 'url' , 'bundle' , 'datetime '] ,
2829 tokenize : ( text : string , fieldName ?: string ) => text . split ( / [ \s \. ] + / ) ,
29- searchOptions : {
30- boost : { text : 2 } ,
31- fuzzy : true ,
32- prefix : true ,
33- } ,
3430} )
3531
3632export const createClipboardStore = ( root : IRootStore ) => {
3733 const store = makeAutoObservable ( {
34+ deleteItem : ( index : number ) => {
35+ if ( index >= 0 && index < store . items . length ) {
36+ minisearch . remove ( store . items [ index ] )
37+ store . items . splice ( index , 1 )
38+ }
39+ } ,
40+ deleteAllItems : ( ) => {
41+ store . items = [ ]
42+ minisearch . removeAll ( )
43+ } ,
3844 items : [ ] as PasteItem [ ] ,
3945 saveHistory : false ,
40- onFileCopied : ( obj : { text : string ; url : string ; bundle : string | null } ) => {
41- let newItem = { id : + Date . now ( ) , ...obj }
42-
43- console . warn ( `Received copied file! ${ JSON . stringify ( newItem ) } ` )
46+ onFileCopied : ( obj : { text : string ; url : string ; bundle : string | null } ) => {
47+ let newItem : PasteItem = { id : + Date . now ( ) , datetime : Date . now ( ) , ...obj }
4448
4549 // If save history move file to more permanent storage
4650 if ( store . saveHistory ) {
@@ -65,12 +69,12 @@ export const createClipboardStore = (root: IRootStore) => {
6569 // Remove last item from minisearch
6670 store . removeLastItemIfNeeded ( )
6771 } ,
68- onTextCopied : ( obj : { text : string ; bundle : string | null } ) => {
72+ onTextCopied : ( obj : { text : string ; bundle : string | null } ) => {
6973 if ( ! obj . text ) {
7074 return
7175 }
7276
73- let newItem = { id : Date . now ( ) . valueOf ( ) , ... obj }
77+ let newItem : PasteItem = { id : Date . now ( ) . valueOf ( ) , datetime : Date . now ( ) , ... obj }
7478
7579 const index = store . items . findIndex ( t => t . text === newItem . text )
7680 // Item already exists, move to top
@@ -91,11 +95,27 @@ export const createClipboardStore = (root: IRootStore) => {
9195 store . removeLastItemIfNeeded ( )
9296 } ,
9397 get clipboardItems ( ) : PasteItem [ ] {
98+ let items = store . items ;
99+
94100 if ( ! root . ui . query || root . ui . focusedWidget !== Widget . CLIPBOARD ) {
95- return root . clipboard . items
101+ return items
96102 }
97103
98- return minisearch . search ( root . ui . query ) as any
104+ // Boost recent items in search results
105+ const now = Date . now ( ) ;
106+ return minisearch . search ( root . ui . query , {
107+ boostDocument : ( documentId , term , storedFields ) => {
108+ const dt = typeof storedFields ?. datetime === 'number' ? storedFields . datetime : Number ( storedFields ?. datetime ) ;
109+ if ( ! dt || isNaN ( dt ) ) return 1 ;
110+ // Boost items copied in the last 24h, scale down for older
111+ const hoursAgo = ( now - dt ) / ( 1000 * 60 * 60 ) ;
112+ if ( hoursAgo < 1 ) return 2 ; // very recent
113+ if ( hoursAgo < 24 ) return 1.5 ; // recent
114+ return 1 ;
115+ } ,
116+ boost : { text : 2 } ,
117+ fuzzy : true ,
118+ } ) as any
99119 } ,
100120 removeLastItemIfNeeded : ( ) => {
101121 if ( store . items . length > MAX_ITEMS ) {
@@ -160,7 +180,13 @@ export const createClipboardStore = (root: IRootStore) => {
160180
161181 if ( entry ) {
162182 let items = JSON . parse ( entry )
163-
183+ // Ensure all items have datetime
184+ items = items . map ( ( item : any ) => ( {
185+ ...item ,
186+ datetime : typeof item . datetime === 'number' && ! isNaN ( item . datetime )
187+ ? item . datetime
188+ : ( item . id || Date . now ( ) ) , // fallback: use id or now
189+ } ) )
164190 runInAction ( ( ) => {
165191 store . items = items
166192 minisearch . addAll ( store . items )
@@ -171,18 +197,24 @@ export const createClipboardStore = (root: IRootStore) => {
171197
172198 const persist = async ( ) => {
173199 if ( store . saveHistory ) {
174- const history = toJS ( store )
200+ // Ensure all items have datetime before persisting
201+ const itemsToPersist = store . items . map ( item => ( {
202+ ...item ,
203+ datetime : typeof item . datetime === 'number' && ! isNaN ( item . datetime )
204+ ? item . datetime
205+ : ( item . id || Date . now ( ) ) ,
206+ } ) )
175207 try {
176208 await solNative . securelyStore (
177209 '@sol.clipboard_history_v2' ,
178- JSON . stringify ( history . items ) ,
210+ JSON . stringify ( itemsToPersist ) ,
179211 )
180212 } catch ( e ) {
181213 console . warn ( 'Could not persist data' , e )
182214 }
183215 }
184216
185- let storeWithoutItems = { ...store }
217+ let storeWithoutItems = { ...store }
186218 storeWithoutItems . items = [ ]
187219
188220 try {
0 commit comments