Skip to content

Commit

Permalink
Fix loading state, add bluetooth icons
Browse files Browse the repository at this point in the history
  • Loading branch information
ziulev committed Dec 14, 2021
1 parent fdbf385 commit 5f92635
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 50 deletions.
5 changes: 2 additions & 3 deletions apps/spotter/src/components/queryPanel/options.queryPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,7 @@ export const Option = ({
}
</View>
}
const uriRegExp = /(\/.*\.\w+)/g;
export const OptionIcon = ({ style, icon }: { style: ViewStyle & ImageStyle, icon?: Icon }) => {
export const OptionIcon = ({ style, icon }: { style?: ViewStyle & ImageStyle, icon?: Icon }) => {
return <>
{icon
? <View style={{
Expand All @@ -150,7 +149,7 @@ export const OptionIcon = ({ style, icon }: { style: ViewStyle & ImageStyle, ico
}}>
{icon.endsWith('.app') || icon.endsWith('.prefPane')
? <IconImage style={{ width: 25, height: 25 }} source={icon}></IconImage>
: uriRegExp.test(icon) || icon.startsWith('https://') || icon.startsWith('http://')
: icon.endsWith('.png') || icon.startsWith('https://') || icon.startsWith('http://')
? <Image style={{ width: 22, height: 22 }} source={{ uri: icon }}></Image>
: <Text style={{ margin: 'auto' }}>{icon}</Text>
}
Expand Down
29 changes: 19 additions & 10 deletions apps/spotter/src/components/queryPanel/queryPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,27 @@ export const QueryPanel: FC<{}> = () => {

<View style={{marginLeft: 10}}>
{loading
? <ActivityIndicator size="small" color={colors?.activeOptionBackground} style={{
opacity: 0.3,
right: 3,
bottom: 0,
top: 0,
margin: 'auto',
position: 'absolute',
zIndex: 100,
}} />
? <ActivityIndicator
size="small"
color={colors?.text}
style={{
opacity: 0.75,
right: 3,
bottom: 0,
top: 0,
margin: 'auto',
position: 'absolute',
zIndex: 100,
}}
/>
: null
}
{options[hoveredOptionIndex] && <OptionIcon style={{}} icon={options[hoveredOptionIndex].icon}></OptionIcon>}
{
(options[hoveredOptionIndex] && !loading) &&
<OptionIcon style={{
opacity: loading ? 0.1 : 1,
}} icon={options[hoveredOptionIndex].icon}></OptionIcon>
}
</View>

</View>
Expand Down
8 changes: 7 additions & 1 deletion apps/spotter/src/providers/plugins.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const PluginsProvider: FC<{}> = (props) => {
displayedOptionsForCurrentWorkflow$,
placeholder$,
hoveredOptionIndex$,
loading$,
resetState,
} = useSpotterState();

Expand Down Expand Up @@ -380,7 +381,7 @@ export const PluginsProvider: FC<{}> = (props) => {
}

if (command.type === CommandType.setError) {
Alert.alert(command.value ?? `${command.pluginName} error...`);
Alert.alert(command.value);
return;
}

Expand All @@ -404,6 +405,11 @@ export const PluginsProvider: FC<{}> = (props) => {
return;
}

if (command.type === CommandType.setLoading) {
loading$.next(command.value);
return;
}

if (command.type === CommandType.open) {
panel.open();
return;
Expand Down
5 changes: 4 additions & 1 deletion apps/spotter/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
"strict": true,
"target": "esnext",
"resolveJsonModule": true,
"rootDir": ".",
"rootDirs": [
".",
"../../packages/core",
],
"paths": {
"@spotter-app/core": ["../../packages/core/index.ts"],
}
Expand Down
49 changes: 28 additions & 21 deletions packages/bluetooth-plugin/src/bluetooth-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ url.pop();
const path = url.join('/');

new class CalculatorPlugin extends Plugin {
private appPath = '/Applications/Visual Studio Code.app';
private activeIcon = `${path}/icons/active.png`;
private inactiveIcon = `${path}/icons/inactive.png`;

constructor() {
super('bluetooth-plugin');
Expand All @@ -22,30 +23,32 @@ new class CalculatorPlugin extends Plugin {
this.spotter.setRegisteredOptions([{
title: 'Bluetooth',
prefix: 'blt',
icon: this.appPath,
onQuery: async (q: string) => await this.getFolders(q),
icon: this.activeIcon,
onQuery: async (q: string) => await this.getDevicesOptions(q),
}]);
}

private async getFolders(q: string): Promise<OnQueryOption[]> {
private async getDevicesOptions(q: string, hoveredId?: string): Promise<OnQueryOption[]> {
const pairedDevices: Device[] = await promisedExec(`${path}/blueutil --paired`)
.then(result => result
.split('\n')
.filter(d => !!d)
.map(d => ({
title: /name: (.+?),/.exec(d)[1].replaceAll('"', ''),
id: /address: (.+?),/.exec(d)[1].replaceAll('"', ''),
connected: !d.includes('not connected'),
}))
)
.catch(() => []);
.then(result => result
.split('\n')
.filter(d => !!d)
.map(d => ({
title: /name: (.+?),/.exec(d)[1].replaceAll('"', ''),
id: /address: (.+?),/.exec(d)[1].replaceAll('"', ''),
connected: !d.includes('not connected'),
}))
)
.catch(() => []);

const options = pairedDevices.map(device => ({
const options: OnQueryOption[] = pairedDevices.map(device => ({
title: device.title,
subtitle: device.connected ? 'Disconnect' : 'Connect',
icon: device.connected ? this.activeIcon : this.inactiveIcon,
hovered: device.id === hoveredId,
onSubmit: async () => device.connected
? await this.disconnect(device)
: await this.connect(device)
? await this.disconnect(device, q)
: await this.connect(device, q)
}));

if (!q.length) {
Expand All @@ -55,25 +58,29 @@ new class CalculatorPlugin extends Plugin {
return options.filter(o => o.title.toLowerCase().split(' ').find(t => t.startsWith(q.toLowerCase())));
}

private async connect(device: Device) {
private async connect(device: Device, query: string) {
const result = await promisedExec(`${path}/blueutil --connect ${device.id} --info ${device.id}`)
.then(() => true)
.catch(() => false);

if (!result) {
this.spotter.setError(`Can not connect ${device.title}`);
}
return result;

return await this.getDevicesOptions(query, device.id);
}

private async disconnect(device: Device) {
private async disconnect(device: Device, query: string) {
const result = await promisedExec(`${path}/blueutil --disconnect ${device.id} --info ${device.id}`)
.then(() => true)
.catch(() => false);

if (!result) {
this.spotter.setError(`Can not connect ${device.title}`);
}
return result;

return new Promise<OnQueryOption[]>(res => setTimeout(async () => {
res(await this.getDevicesOptions(query, device.id))
}, 2500));
}
}
Binary file added packages/bluetooth-plugin/src/icons/active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/bluetooth-plugin/src/icons/inactive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
6 changes: 3 additions & 3 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './src/interfaces';
export * from './src/plugin';
export * from './src/helpers';
export * from './interfaces';
export * from './plugin';
export * from './helpers';
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export enum CommandType {
updatePlugin = 'updatePlugin',
removePlugin = 'removePlugin',
setTheme = 'setTheme',
setLoading = 'setLoading',
open = 'open',
close = 'close',
}
Expand Down Expand Up @@ -163,6 +164,9 @@ export type Command = {
} | {
type: CommandType.setTheme,
value: string,
} | {
type: CommandType.setLoading,
value: boolean,
} | {
type: CommandType.open,
} | {
Expand Down
48 changes: 37 additions & 11 deletions packages/core/src/plugin.ts → packages/core/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Subject, filter, lastValueFrom, map, first } from 'rxjs';
import {
SpotterOption,
Command,
CommandType,
Settings,
SpotterCommand,
Expand Down Expand Up @@ -43,7 +42,7 @@ export class SpotterPlugin {
private spotterGetSettings = (): Promise<Settings> => {
const id = generateId();
this.spotterSendCommand(CommandType.getSettings, id);
return this.spotterReciveDataWithId<Settings>(id);
return this.spotterReceiveDataWithId<Settings>(id);
}

private spotterPatchSettings = (value: Partial<Settings>) => {
Expand All @@ -53,7 +52,7 @@ export class SpotterPlugin {
private spotterGetStorage = <T>(): Promise<Storage<T>> => {
const id = generateId();
this.spotterSendCommand(CommandType.getStorage, id);
return this.spotterReciveDataWithId<Storage<T>>(id);
return this.spotterReceiveDataWithId<Storage<T>>(id);
}

private spotterPatchStorage = <T>(value: Partial<Storage<T>>) => {
Expand All @@ -69,7 +68,7 @@ export class SpotterPlugin {
this.spotterSendCommand(CommandType.setRegisteredOptions, value);
}

private sptoterPatchRegisteredOptions = (input: RegistryOption[]) => {
private spotterPatchRegisteredOptions = (input: RegistryOption[]) => {
const value = this.spotterRegistredOptionsToSpotterRegistredOptions(input);
this.spotterSendCommand(CommandType.patchRegisteredOptions, value);
}
Expand All @@ -83,7 +82,7 @@ export class SpotterPlugin {
this.spotterSendCommand(CommandType.setPlaceholder, value);
}

private sptoterSetQuery = (value: string) => {
private spotterSetQuery = (value: string) => {
this.spotterSendCommand(CommandType.setQuery, value);
}

Expand All @@ -102,7 +101,7 @@ export class SpotterPlugin {
private spotterGetPlugins = () => {
const id = generateId();
this.spotterSendCommand(CommandType.getPlugins, id);
return this.spotterReciveDataWithId<PluginRegistryEntry[]>(id);
return this.spotterReceiveDataWithId<PluginRegistryEntry[]>(id);
}

private spotterAddPlugin = (value: string) => {
Expand All @@ -125,16 +124,20 @@ export class SpotterPlugin {
this.spotterSendCommand(CommandType.setTheme, value);
}

private spotterSetLoading = (value: boolean) => {
this.spotterSendCommand(CommandType.setLoading, value);
}

readonly spotter = {
getSettings: this.spotterGetSettings,
patchSettings: this.spotterPatchSettings,
getStorage: this.spotterGetStorage,
setStorage: this.spotterSetStorage,
patchStorage: this.spotterPatchStorage,
setRegisteredOptions: this.spotterSetRegisteredOptions,
patchRegisteredOptions: this.sptoterPatchRegisteredOptions,
patchRegisteredOptions: this.spotterPatchRegisteredOptions,
setPlaceholder: this.spotterSetPlaceholder,
setQuery: this.sptoterSetQuery,
setQuery: this.spotterSetQuery,
setError: this.spotterSetError,
open: this.spotterOpen,
close: this.spotterClose,
Expand Down Expand Up @@ -228,7 +231,7 @@ export class SpotterPlugin {
});
}

private spotterReciveDataWithId<T>(id: string): Promise<T> {
private spotterReceiveDataWithId<T>(id: string): Promise<T> {
return lastValueFrom(
this.getDataCommand.pipe(
filter(command => command.id === id),
Expand All @@ -238,7 +241,6 @@ export class SpotterPlugin {
) as Promise<T>;
}

// function func(p1: TypeA, p2: ab): void;
private spotterSendCommand(type: CommandType.startPluginScript, value: string): void;
private spotterSendCommand(type: CommandType.close, value?: null): void;
private spotterSendCommand(type: CommandType.getPlugins, value: string): void;
Expand All @@ -260,14 +262,15 @@ export class SpotterPlugin {
private spotterSendCommand(type: CommandType.updatePlugin, value: string): void;
private spotterSendCommand(type: CommandType.removePlugin, value: string): void;
private spotterSendCommand(type: CommandType.setTheme, value: string): void;
private spotterSendCommand(type: CommandType.setLoading, value: boolean): void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private spotterSendCommand(type: CommandType, value: any) {
if (!this.channel) {
console.error(CHANNEL_ERROR);
return;
}

const command: Command = {
const command = {
type,
value,
};
Expand Down Expand Up @@ -314,6 +317,13 @@ export class SpotterPlugin {
return;
}

if (
command.type !== SpotterCommandType.onHover &&
command.type !== SpotterCommandType.onQueryCancel
) {
this.spotterSetLoading(true);
}

const result: ActionResult = await action.bind(this)(
command.type === SpotterCommandType.onQuery
? command.query
Expand All @@ -322,14 +332,30 @@ export class SpotterPlugin {

if (Array.isArray(result)) {
this.spotterSetOnQueryOptions(result);

if (
command.type !== SpotterCommandType.onHover &&
command.type !== SpotterCommandType.onQueryCancel
) {
this.spotterSetLoading(false);
}
return;
}

if (typeof result === 'boolean' && !result) {
if (
command.type !== SpotterCommandType.onHover &&
command.type !== SpotterCommandType.onQueryCancel
) {
this.spotterSetLoading(false);
}
return;
}

if (command.type !== SpotterCommandType.onHover) {
if (command.type !== SpotterCommandType.onQueryCancel) {
this.spotterSetLoading(false);
}
this.spotterClose();
}
return;
Expand Down

0 comments on commit 5f92635

Please sign in to comment.