This repository has been archived by the owner on Sep 26, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for custom recents providers (#202)
- Loading branch information
1 parent
a94914e
commit 848ee8b
Showing
22 changed files
with
294 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Recent emojis | ||
|
||
PicMo will keep track of your most recently used emojis in the "Recently Used" category. As emojis are selected, they will be added to the "Recently Used" category. | ||
|
||
## Recents providers | ||
|
||
### Built-in web storage providers | ||
|
||
By default, recent emoji data is kept in [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). This is managed by the [`LocalStorageProvider`](../api/picmo/classes/local-storage-provider) class. | ||
|
||
PicMo also includes a [`SessionStorageProvider`](../api/picmo/classes/session-storage-provider) class that uses [session storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) instead. | ||
|
||
A provider is selected by passing a `recentsProvider` option to the [`createPicker`](../api/picmo/functions/create-picker) function. The value should be an *instance* of the provider class. | ||
|
||
### Creating a custom recents provider | ||
|
||
You can create a custom provider to store recent emojis in some other way. To do this, you need to create a class that extends from the [`RecentsProvider`](../api/picmo/classes/recents-provider) class and implement the three methods required (`clear`, `getRecents`, and `addOrUpdateRecent`). | ||
|
||
An instance of this class should be passed to the `recentsProvider` option of the [`createPicker`](../api/picmo/functions/create-picker) function. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# `LocalStorageProvider` | ||
|
||
A [`RecentsProvider`](./recents-provider) that uses [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to store the recent emojis. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# `RecentsProvider` | ||
|
||
Abstract base class that provides a storage mechanism for remembering recently selected emojis. | ||
|
||
To create a custom recents provider, create a subclass of `RecentsProvider`. | ||
|
||
``` | ||
import { RecentsProvider } from 'picmo'; | ||
``` | ||
|
||
## Methods | ||
|
||
### `clear` | ||
|
||
``` | ||
clear(): void | ||
``` | ||
|
||
Removes all stored recent emojis. | ||
|
||
### `getRecents` | ||
|
||
<pre> | ||
getRecents(maxCount: number): <a href="../types/emoji-record">EmojiRecord</a>[] | ||
</pre> | ||
|
||
Gets the current set of recent emojis. The returned list will be truncated to satisfy the `maxCount` parameter. | ||
|
||
### `addOrUpdateRecent` | ||
|
||
<pre> | ||
addOrUpdateRecent(emoji: <a href="../types/emoji-record">EmojiRecord</a>, maxCount: number): void | ||
</pre> | ||
|
||
Adds a new recent emoji to the list, or updates an existing one if it already exists. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# `SessionStorageProvider` | ||
|
||
A [`RecentsProvider`](./recents-provider) that uses [session storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to store the recent emojis. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# `EmojiRecord` | ||
|
||
Describes a single emoji inside the picker. | ||
|
||
This is _not_ what is emitted when an emoji is selected; for that, see [`EmojiSelection`](./emoji-selection). Rather, it is used internally by the picker as well as the recents provider. | ||
|
||
## Properties | ||
|
||
### `custom` | ||
|
||
- **Type**: `boolean` | `undefined` | ||
|
||
Whether or not this is a custom emoji. | ||
|
||
### `data` | ||
|
||
- **Type**: `any` | `undefined` | ||
|
||
Arbitrary data associated with an emoji. Only applies to custom emojis. | ||
|
||
### `emoji` | ||
|
||
- **Type**: `string` | ||
|
||
The native emoji string containing the Unicode sequenece for the emoji. For custom emojis, this is a unique identifier for the custom emoji. | ||
|
||
### `hexcode` | ||
|
||
- **Type**: `string` | `undefined` | ||
|
||
The hex codes for the emoji, separated by hyphens, e.g. `'1F3CB-1F3FB-200D-2642-FE0F'`. | ||
|
||
Only applies to non-custom emojis. | ||
|
||
### `label` | ||
|
||
- **Type**: `string` | ||
|
||
The display name for the emoji. | ||
|
||
### `order` | ||
|
||
- **Type**: `number` | `undefined` | ||
|
||
The order of the emoji within its category. | ||
|
||
Only applies to non-custom emojis; custom emojis are ordered depending on their order in the `custom` array. | ||
|
||
### `skins` | ||
|
||
- **Type**: `EmojiRecord[]` | `undefined` | ||
|
||
Any variants of the emoji, typically for different skin tones, though sometimes they can be for other attributes such as hair color. | ||
|
||
### `tags` | ||
|
||
- **Type**: `string[]` | `undefined` | ||
|
||
An array of tags for this emoji, if any. | ||
|
||
### `url` | ||
|
||
- **Type**: `string` | `undefined` | ||
|
||
For custom emojis, the URL of the image to use for the emoji. | ||
|
||
Only applies to custom emojis. | ||
|
||
### `version` | ||
|
||
- **Type**: `number` | `undefined` | ||
|
||
For non-custom emojis, specifies the version of the Emoji specification that the emoji was added in. | ||
|
||
Only applies to non-custom emojis. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,20 @@ | ||
import { EmojiRecord } from './types'; | ||
import { RecentsProvider } from './recents/RecentsProvider'; | ||
|
||
const LOCAL_STORAGE_KEY = 'PicMo:recents'; | ||
// Deprecated legacy interface to clear recents for backwards compatibility. | ||
// This should not be used by new code; instead, call clear() on the | ||
// RecentsProvider itself. | ||
|
||
export function clear(): void { | ||
localStorage.removeItem(LOCAL_STORAGE_KEY); | ||
} | ||
// It's a little odd and won't work well with a custom provider, but leaving it in | ||
// so as not to create breaking changes. | ||
|
||
// @deprecated Remove in 6.0.0. | ||
|
||
export function getRecents(maxCount: number): Array<EmojiRecord> { | ||
try { | ||
const recents = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) ?? '[]'); | ||
return recents.slice(0, maxCount); | ||
} catch (error) { // localStorage is not available, no recents | ||
return []; | ||
} | ||
let provider: RecentsProvider; | ||
|
||
export function setProvider(_provider: RecentsProvider) { | ||
provider = _provider; | ||
} | ||
|
||
export function addOrUpdateRecent(emoji: EmojiRecord, maxCount: number) { | ||
// Add the new recent to the beginning of the list, removing it if it exists already | ||
const recents = [ | ||
emoji, | ||
...getRecents(maxCount).filter(recent => recent.hexcode !== emoji.hexcode) | ||
].slice(0, maxCount); | ||
|
||
try { | ||
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(recents)); | ||
} catch (error) { | ||
// localStorage is not available, no recents | ||
} | ||
export function clear(): void { | ||
provider.clear(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { WebStorageProvider } from './WebStorageProvider'; | ||
|
||
export class LocalStorageProvider extends WebStorageProvider { | ||
constructor() { | ||
super(localStorage); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { EmojiRecord } from '../types'; | ||
|
||
export abstract class RecentsProvider { | ||
abstract clear(): void; | ||
abstract getRecents(maxCount: number): Array<EmojiRecord>; | ||
abstract addOrUpdateRecent(emoji: EmojiRecord, maxCount: number): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { WebStorageProvider } from './WebStorageProvider'; | ||
|
||
export class SessionStorageProvider extends WebStorageProvider { | ||
constructor() { | ||
super(sessionStorage); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { EmojiRecord } from '../types'; | ||
import { RecentsProvider } from './RecentsProvider'; | ||
|
||
const STORAGE_KEY = 'PicMo:recents'; | ||
|
||
export abstract class WebStorageProvider extends RecentsProvider { | ||
storage: Storage; | ||
|
||
constructor(storage: Storage) { | ||
super(); | ||
this.storage = storage; | ||
} | ||
|
||
clear(): void { | ||
this.storage.removeItem(STORAGE_KEY); | ||
} | ||
|
||
getRecents(maxCount: number): Array<EmojiRecord> { | ||
try { | ||
const recents = JSON.parse(this.storage.getItem(STORAGE_KEY) ?? '[]'); | ||
return recents.slice(0, maxCount); | ||
} catch (error) { // storage is not available, no recents | ||
return []; | ||
} | ||
} | ||
|
||
addOrUpdateRecent(emoji: EmojiRecord, maxCount: number) { | ||
// Add the new recent to the beginning of the list, removing it if it exists already | ||
const recents = [ | ||
emoji, | ||
...this.getRecents(maxCount).filter(recent => recent.hexcode !== emoji.hexcode) | ||
].slice(0, maxCount); | ||
|
||
try { | ||
this.storage.setItem(STORAGE_KEY, JSON.stringify(recents)); | ||
} catch (error) { | ||
console.warn('storage is not available, recent emojis will not be saved'); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { LocalStorageProvider } from './LocalStorageProvider'; | ||
export { SessionStorageProvider } from './SessionStorageProvider'; | ||
export { RecentsProvider } from './RecentsProvider'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.