Merge pull request #4040 from janhq/fix/rerender-component
chore: refactor rerender components
This commit is contained in:
commit
7a084b6589
@ -113,7 +113,6 @@ export abstract class BaseExtension implements ExtensionType {
|
|||||||
for (const model of models) {
|
for (const model of models) {
|
||||||
ModelManager.instance().register(model)
|
ModelManager.instance().register(model)
|
||||||
}
|
}
|
||||||
events.emit(ModelEvent.OnModelsUpdate, {})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -28,6 +28,7 @@ class WindowManager {
|
|||||||
...mainWindowConfig,
|
...mainWindowConfig,
|
||||||
width: bounds.width,
|
width: bounds.width,
|
||||||
height: bounds.height,
|
height: bounds.height,
|
||||||
|
show: false,
|
||||||
x: bounds.x,
|
x: bounds.x,
|
||||||
y: bounds.y,
|
y: bounds.y,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
@ -78,6 +79,10 @@ class WindowManager {
|
|||||||
windowManager.hideMainWindow()
|
windowManager.hideMainWindow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
windowManager.mainWindow?.on('ready-to-show', function () {
|
||||||
|
windowManager.mainWindow?.show()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
createQuickAskWindow(preloadPath: string, startUrl: string): void {
|
createQuickAskWindow(preloadPath: string, startUrl: string): void {
|
||||||
|
|||||||
@ -228,7 +228,9 @@ export default class JanInferenceCortexExtension extends LocalOAIEngine {
|
|||||||
// Delay for the state update from cortex.cpp
|
// Delay for the state update from cortex.cpp
|
||||||
// Just to be sure
|
// Just to be sure
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
events.emit(ModelEvent.OnModelsUpdate, {})
|
events.emit(ModelEvent.OnModelsUpdate, {
|
||||||
|
fetch: true,
|
||||||
|
})
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -40,11 +40,6 @@ export default class JanModelExtension extends ModelExtension {
|
|||||||
async onLoad() {
|
async onLoad() {
|
||||||
this.registerSettings(SETTINGS)
|
this.registerSettings(SETTINGS)
|
||||||
|
|
||||||
// Try get models from cortex.cpp
|
|
||||||
this.getModels().then((models) => {
|
|
||||||
this.registerModels(models)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Listen to app download events
|
// Listen to app download events
|
||||||
this.handleDesktopEvents()
|
this.handleDesktopEvents()
|
||||||
}
|
}
|
||||||
@ -163,19 +158,27 @@ export default class JanModelExtension extends ModelExtension {
|
|||||||
(e) => e.engine === InferenceEngine.nitro
|
(e) => e.engine === InferenceEngine.nitro
|
||||||
)
|
)
|
||||||
|
|
||||||
await this.cortexAPI.getModels().then((models) => {
|
/**
|
||||||
const existingIds = models.map((e) => e.id)
|
* Fetch models from cortex.cpp
|
||||||
toImportModels = toImportModels.filter(
|
*/
|
||||||
(e: Model) => !existingIds.includes(e.id) && !e.settings?.vision_model
|
var fetchedModels = await this.cortexAPI.getModels().catch(() => [])
|
||||||
)
|
|
||||||
})
|
// Checking if there are models to import
|
||||||
|
const existingIds = fetchedModels.map((e) => e.id)
|
||||||
|
toImportModels = toImportModels.filter(
|
||||||
|
(e: Model) => !existingIds.includes(e.id) && !e.settings?.vision_model
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There is no model to import
|
||||||
|
* just return fetched models
|
||||||
|
*/
|
||||||
|
if (!toImportModels.length) return fetchedModels
|
||||||
|
|
||||||
console.log('To import models:', toImportModels.length)
|
console.log('To import models:', toImportModels.length)
|
||||||
/**
|
/**
|
||||||
* There are models to import
|
* There are models to import
|
||||||
* do not return models from cortex.cpp yet
|
*/
|
||||||
* otherwise it will reset the app cache
|
|
||||||
* */
|
|
||||||
if (toImportModels.length > 0) {
|
if (toImportModels.length > 0) {
|
||||||
// Import models
|
// Import models
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
@ -202,8 +205,6 @@ export default class JanModelExtension extends ModelExtension {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
return currentModels
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -29,13 +29,19 @@ const DataLoader: React.FC<Props> = ({ children }) => {
|
|||||||
const setQuickAskEnabled = useSetAtom(quickAskEnabledAtom)
|
const setQuickAskEnabled = useSetAtom(quickAskEnabledAtom)
|
||||||
const setJanDefaultDataFolder = useSetAtom(defaultJanDataFolderAtom)
|
const setJanDefaultDataFolder = useSetAtom(defaultJanDataFolderAtom)
|
||||||
const setJanSettingScreen = useSetAtom(janSettingScreenAtom)
|
const setJanSettingScreen = useSetAtom(janSettingScreenAtom)
|
||||||
|
const { loadDataModel } = useModels()
|
||||||
|
|
||||||
useModels()
|
|
||||||
useThreads()
|
useThreads()
|
||||||
useAssistants()
|
useAssistants()
|
||||||
useGetSystemResources()
|
useGetSystemResources()
|
||||||
useLoadTheme()
|
useLoadTheme()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Load data once
|
||||||
|
loadDataModel()
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.core?.api
|
window.core?.api
|
||||||
?.getAppConfigurations()
|
?.getAppConfigurations()
|
||||||
|
|||||||
@ -112,8 +112,8 @@ const EventListenerWrapper = ({ children }: PropsWithChildren) => {
|
|||||||
state.downloadState = 'end'
|
state.downloadState = 'end'
|
||||||
setDownloadState(state)
|
setDownloadState(state)
|
||||||
removeDownloadingModel(state.modelId)
|
removeDownloadingModel(state.modelId)
|
||||||
|
events.emit(ModelEvent.OnModelsUpdate, { fetch: true })
|
||||||
}
|
}
|
||||||
events.emit(ModelEvent.OnModelsUpdate, {})
|
|
||||||
},
|
},
|
||||||
[removeDownloadingModel, setDownloadState]
|
[removeDownloadingModel, setDownloadState]
|
||||||
)
|
)
|
||||||
|
|||||||
@ -43,7 +43,7 @@ const ModelImportListener = ({ children }: PropsWithChildren) => {
|
|||||||
const onImportModelSuccess = useCallback(
|
const onImportModelSuccess = useCallback(
|
||||||
(state: ImportingModel) => {
|
(state: ImportingModel) => {
|
||||||
if (!state.modelId) return
|
if (!state.modelId) return
|
||||||
events.emit(ModelEvent.OnModelsUpdate, {})
|
events.emit(ModelEvent.OnModelsUpdate, { fetch: true })
|
||||||
setImportingModelSuccess(state.importId, state.modelId)
|
setImportingModelSuccess(state.importId, state.modelId)
|
||||||
},
|
},
|
||||||
[setImportingModelSuccess]
|
[setImportingModelSuccess]
|
||||||
|
|||||||
@ -42,8 +42,9 @@ describe('useModels', () => {
|
|||||||
|
|
||||||
jest.spyOn(extensionManager, 'get').mockReturnValue(mockModelExtension)
|
jest.spyOn(extensionManager, 'get').mockReturnValue(mockModelExtension)
|
||||||
|
|
||||||
act(() => {
|
const { result } = renderHook(() => useModels())
|
||||||
renderHook(() => useModels())
|
await act(() => {
|
||||||
|
result.current?.loadDataModel()
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(mockModelExtension.getModels).toHaveBeenCalled()
|
expect(mockModelExtension.getModels).toHaveBeenCalled()
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
ModelManager,
|
ModelManager,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
|
|
||||||
import { useSetAtom } from 'jotai'
|
import { useSetAtom, useAtom } from 'jotai'
|
||||||
|
|
||||||
import { useDebouncedCallback } from 'use-debounce'
|
import { useDebouncedCallback } from 'use-debounce'
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ import {
|
|||||||
* and updates the atoms accordingly.
|
* and updates the atoms accordingly.
|
||||||
*/
|
*/
|
||||||
const useModels = () => {
|
const useModels = () => {
|
||||||
const setDownloadedModels = useSetAtom(downloadedModelsAtom)
|
const [downloadedModels, setDownloadedModels] = useAtom(downloadedModelsAtom)
|
||||||
const setExtensionModels = useSetAtom(configuredModelsAtom)
|
const setExtensionModels = useSetAtom(configuredModelsAtom)
|
||||||
|
|
||||||
const getData = useCallback(() => {
|
const getData = useCallback(() => {
|
||||||
@ -53,9 +53,11 @@ const useModels = () => {
|
|||||||
setDownloadedModels(toUpdate)
|
setDownloadedModels(toUpdate)
|
||||||
|
|
||||||
let isUpdated = false
|
let isUpdated = false
|
||||||
|
|
||||||
toUpdate.forEach((model) => {
|
toUpdate.forEach((model) => {
|
||||||
if (!ModelManager.instance().models.has(model.id)) {
|
if (!ModelManager.instance().models.has(model.id)) {
|
||||||
ModelManager.instance().models.set(model.id, model)
|
ModelManager.instance().models.set(model.id, model)
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
isUpdated = true
|
isUpdated = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -75,21 +77,38 @@ const useModels = () => {
|
|||||||
|
|
||||||
const reloadData = useDebouncedCallback(() => getData(), 300)
|
const reloadData = useDebouncedCallback(() => getData(), 300)
|
||||||
|
|
||||||
useEffect(() => {
|
const updateStates = useCallback(() => {
|
||||||
// Try get data on mount
|
const cachedModels = ModelManager.instance().models.values().toArray()
|
||||||
reloadData()
|
const toUpdate = [
|
||||||
|
...downloadedModels,
|
||||||
|
...cachedModels.filter(
|
||||||
|
(e: Model) => !downloadedModels.some((g: Model) => g.id === e.id)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
setDownloadedModels(toUpdate)
|
||||||
|
}, [downloadedModels, setDownloadedModels])
|
||||||
|
|
||||||
|
const getModels = async (): Promise<Model[]> =>
|
||||||
|
extensionManager
|
||||||
|
.get<ModelExtension>(ExtensionTypeEnum.Model)
|
||||||
|
?.getModels() ?? []
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
// Listen for model updates
|
// Listen for model updates
|
||||||
events.on(ModelEvent.OnModelsUpdate, async () => reloadData())
|
events.on(ModelEvent.OnModelsUpdate, async (data: { fetch?: boolean }) => {
|
||||||
|
if (data.fetch) reloadData()
|
||||||
|
else updateStates()
|
||||||
|
})
|
||||||
return () => {
|
return () => {
|
||||||
// Remove listener on unmount
|
// Remove listener on unmount
|
||||||
events.off(ModelEvent.OnModelsUpdate, async () => {})
|
events.off(ModelEvent.OnModelsUpdate, async () => {})
|
||||||
}
|
}
|
||||||
}, [getData, reloadData])
|
}, [reloadData, updateStates])
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadDataModel: getData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getModels = async (): Promise<Model[]> =>
|
|
||||||
extensionManager.get<ModelExtension>(ExtensionTypeEnum.Model)?.getModels() ??
|
|
||||||
[]
|
|
||||||
|
|
||||||
export default useModels
|
export default useModels
|
||||||
|
|||||||
@ -42,39 +42,6 @@ export const usePath = () => {
|
|||||||
openFileExplorer(fullPath)
|
openFileExplorer(fullPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onViewJson = async (type: string) => {
|
|
||||||
// TODO: this logic should be refactored.
|
|
||||||
if (type !== 'Model' && !activeThread) return
|
|
||||||
|
|
||||||
let filePath = undefined
|
|
||||||
const assistantId = activeThread?.assistants[0]?.assistant_id
|
|
||||||
switch (type) {
|
|
||||||
case 'Engine':
|
|
||||||
case 'Thread':
|
|
||||||
filePath = await joinPath([
|
|
||||||
'threads',
|
|
||||||
activeThread?.id ?? '',
|
|
||||||
'thread.json',
|
|
||||||
])
|
|
||||||
break
|
|
||||||
case 'Model':
|
|
||||||
if (!selectedModel) return
|
|
||||||
filePath = await joinPath(['models', selectedModel.id, 'model.json'])
|
|
||||||
break
|
|
||||||
case 'Assistant':
|
|
||||||
case 'Tools':
|
|
||||||
if (!assistantId) return
|
|
||||||
filePath = await joinPath(['assistants', assistantId, 'assistant.json'])
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filePath) return
|
|
||||||
const fullPath = await joinPath([janDataFolderPath, filePath])
|
|
||||||
openFileExplorer(fullPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onViewFile = async (id: string) => {
|
const onViewFile = async (id: string) => {
|
||||||
if (!activeThread) return
|
if (!activeThread) return
|
||||||
|
|
||||||
@ -99,7 +66,6 @@ export const usePath = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
onRevealInFinder,
|
onRevealInFinder,
|
||||||
onViewJson,
|
|
||||||
onViewFile,
|
onViewFile,
|
||||||
onViewFileContainer,
|
onViewFileContainer,
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user