Skip to content

Commit

Permalink
Merge pull request #15 from Rue-pro/core-add-detect-language-and-remo…
Browse files Browse the repository at this point in the history
…ve-event-handler-to-browser

Core add detect language and remove event handler to browser
  • Loading branch information
Rue-pro authored Apr 8, 2024
2 parents aadfab9 + 1074ced commit 465f978
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 54 deletions.
4 changes: 2 additions & 2 deletions src/entities/tab/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { atom, onMount, task } from 'nanostores'

import { ITab, browser } from '@shared/browser'
import { TTab, browser } from '@shared/browser'
import { addToast, getErrorToast } from '@shared/ui/Toast'

export const $activeTab = atom<ITab | null>(null)
export const $activeTab = atom<TTab | null>(null)

onMount($activeTab, () => {
task(async () => {
Expand Down
27 changes: 24 additions & 3 deletions src/shared/browser/__mocks__/chrome.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { MockedObject, vi } from 'vitest'

import { TOnChangeListenerProps } from '../types'

type TChrome = typeof chrome
type TStorageValue = Record<string, unknown>

let store: TStorageValue = {}
let listeners: Array<(changes: TOnChangeListenerProps) => void> = []

function getStorageValueByKey(key: string) {
const result: TStorageValue = {}
result[key] = store[key]
return result
}

export const chromeMockClearListeners = vi.fn(() => {
listeners = []
})

export const chromeMock = {
storage: {
local: {
Expand All @@ -20,14 +27,28 @@ export const chromeMock = {
}),

set: vi.fn((payload, cb) => {
Object.keys(payload).forEach((key) => (store[key] = payload[key]))
const changes: TOnChangeListenerProps = {}
Object.keys(payload).forEach((key) => {
if (payload[key]) {
store[key] = payload[key]
changes[key] = { oldValue: store[key], newValue: payload[key] }
}
})

for (const listener of listeners) {
listener(changes)
}

return cb ? cb() : Promise.resolve()
}),

onChanged: {
addListener: vi.fn(),
addListener: vi.fn(
(listener: (changes: TOnChangeListenerProps) => void) => {
listeners.push(listener)
},
),
removeListener: vi.fn(),
hasListener: vi.fn(),
},

clear: vi.fn((cb) => {
Expand Down
18 changes: 15 additions & 3 deletions src/shared/browser/__test__/chrome.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,11 @@ describe('browser', () => {
})
})

chromeBrowser.storage.local.onChanged(KEY, callback, defaultValue)
chromeBrowser.storage.local.onChanged.addListener(
KEY,
callback,
defaultValue,
)

expect(callback).toHaveBeenCalledWith(
Result.Success({ newValue, oldValue }),
Expand All @@ -136,7 +140,11 @@ describe('browser', () => {
})
})

chromeBrowser.storage.local.onChanged(KEY, callback, defaultValue)
chromeBrowser.storage.local.onChanged.addListener(
KEY,
callback,
defaultValue,
)

expect(callback).toHaveBeenCalledTimes(2)

Expand Down Expand Up @@ -170,7 +178,11 @@ describe('browser', () => {
})
})

chromeBrowser.storage.local.onChanged(KEY, callback, defaultValue)
chromeBrowser.storage.local.onChanged.addListener(
KEY,
callback,
defaultValue,
)

const call = callback.mock.calls[0]
expect(call[0].data).toBeNull()
Expand Down
80 changes: 49 additions & 31 deletions src/shared/browser/chrome.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { TLanguageCode } from '@entities/language'

import { Result } from '@shared/libs/operationResult'

import { PortReceiver } from './port'
import { IBrowser } from './types'
import { IBrowser, TOnChangeListenerProps } from './types'

export const chromeBrowser: IBrowser = {
storage: {
Expand Down Expand Up @@ -46,39 +48,46 @@ export const chromeBrowser: IBrowser = {
})
},

onChanged: (key, callback, defaultValue) => {
chrome.storage.local.onChanged.addListener((changes) => {
if (changes[key]) {
let oldValue = defaultValue
try {
oldValue = JSON.parse(changes[key].oldValue)
} catch (error) {
callback(
Result.Error({
type: `ERROR_CAN_NOT_GET_OLD_DATA_FROM_STORAGE`,
error: error instanceof Error ? error : null,
}),
)
}
onChanged: {
addListener: (key, callback, defaultValue) => {
const listener = (changes: TOnChangeListenerProps) => {
if (changes[key]) {
let oldValue = defaultValue
try {
oldValue = JSON.parse(changes[key].oldValue as string)
} catch (error) {
callback(
Result.Error({
type: `ERROR_CAN_NOT_GET_OLD_DATA_FROM_STORAGE`,
error: error instanceof Error ? error : null,
}),
)
}

try {
const newValue = JSON.parse(changes[key].newValue)
callback(
Result.Success({
newValue: newValue,
oldValue: oldValue,
}),
)
} catch (error) {
callback(
Result.Error({
type: `ERROR_CAN_NOT_GET_NEW_DATA_FROM_STORAGE`,
error: error instanceof Error ? error : null,
}),
)
try {
const newValue = JSON.parse(changes[key].newValue as string)
callback(
Result.Success({
newValue: newValue,
oldValue: oldValue,
}),
)
} catch (error) {
callback(
Result.Error({
type: `ERROR_CAN_NOT_GET_NEW_DATA_FROM_STORAGE`,
error: error instanceof Error ? error : null,
}),
)
}
}
}
})
chrome.storage.local.onChanged.addListener(listener)
return listener
},
removeListener: (listener) => {
chrome.storage.local.onChanged.removeListener(listener)
},
},
},
},
Expand All @@ -87,6 +96,15 @@ export const chromeBrowser: IBrowser = {
getMessage: (key, substitutions) => {
return chrome.i18n.getMessage(key, substitutions)
},

detectLanguage: async (text: string) => {
if (!text) return 'other'

const detectLanguageResult = await chrome.i18n.detectLanguage(text)

return (detectLanguageResult.languages[0].language ??
'other') as TLanguageCode
},
},

runtime: {
Expand Down
5 changes: 3 additions & 2 deletions src/shared/browser/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { chromeBrowser } from './chrome'
import { IBrowser } from './types'
import type { IBrowser } from './types'

export const browser: IBrowser = chromeBrowser
export type { ITab } from './types'

export type { TTab, TOnChangeListenerProps } from './types'
export * from './port'
45 changes: 32 additions & 13 deletions src/shared/browser/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { TLanguageCode } from '@entities/language'

import type { TResult } from '@shared/libs/operationResult'

import { PortReceiver } from '.'
Expand All @@ -9,21 +11,32 @@ export interface IBrowser {

set: <Data>(key: string, value: Data) => Promise<TResult<true>>

onChanged: <Data>(
key: string,
callback: (
changes: TResult<{
newValue: Data
oldValue: Data
}>,
) => void,
defaultValue: Data,
) => void
onChanged: {
addListener: <Data>(
key: string,
callback: (
changes: TResult<{
newValue: Data
oldValue: Data
}>,
) => void,
defaultValue: Data,
) => (changes: {
[key: string]: { newValue?: Data; oldValue?: Data }
}) => void
removeListener: <Data>(
callback: (changes: {
[key: string]: { newValue?: Data; oldValue?: Data }
}) => void,
) => void
}
}
}

i18n: {
getMessage: (key: string, substitutions?: string | string[]) => string

detectLanguage: (text: string) => Promise<TLanguageCode>
}

runtime: {
Expand All @@ -33,9 +46,15 @@ export interface IBrowser {
}

tabs: {
getActiveTab: () => Promise<TResult<ITab>>
getActiveTab: () => Promise<TResult<TTab>>
}
}

export type ITab = { id: number; url: string }
export type IActiveTabInfo = { tabId: number }
export type TTab = { id: number; url: string }
export type TActiveTabInfo = { tabId: number }
export type TOnChangeListenerProps<Value = unknown> = {
[key: string]: {
newValue?: Value
oldValue?: Value
}
}

0 comments on commit 465f978

Please sign in to comment.