Skip to content

Commit

Permalink
feat: support multiple layer key label display and add symbol layer
Browse files Browse the repository at this point in the history
  • Loading branch information
andy23512 committed May 7, 2024
1 parent 20a386b commit 4e5ab23
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/app/components/layout/layout.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
[rotation]="sw.startsWith('thumb') ? 10 : 0"
[keyLabelMap]="keyLabelMap()"
[positionCodeMap]="positionCodeLayout[side][sw]"
[highlightPositionCodes]="highlightPositionCodes()"
[highlightKey]="highlightKey()"
></g>
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/app/components/layout/layout.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import {
} from '@angular/core';
import { LetDirective } from '@ngrx/component';
import { POSITION_CODE_LAYOUT } from 'src/app/data/layouts';
import {
CharaChorderOneCharacterKey,
CharaChorderOneKeyLabel,
} from 'src/app/models/device-layout.models';
import { FingerMap, HandMap } from 'src/app/models/layout.models';
import { humanizePositionCode } from 'src/app/utils/layout.utils';
import { SwitchComponent } from '../switch/switch.component';
Expand All @@ -22,11 +26,14 @@ const gap = 35;
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LayoutComponent {
readonly keyLabelMap = input<Record<number, string>>({});
readonly highlightPositionCodes = input<number[]>([]);
readonly keyLabelMap = input<Record<number, CharaChorderOneKeyLabel[]>>({});
readonly highlightKey = input<CharaChorderOneCharacterKey | null>(null);

readonly highlightPositionCodesInText = computed(() => {
const highlightPositionCodes = this.highlightPositionCodes();
const highlightPositionCodes = this.highlightKey()?.positionCodes;
if (!highlightPositionCodes) {
return '';
}
return [...highlightPositionCodes]
.reverse()
.map(humanizePositionCode)
Expand Down
36 changes: 24 additions & 12 deletions src/app/components/switch-sector/switch-sector.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,28 @@
<svg:path
class="fill-alnitak-500"
[attr.d]="sectorPath() + ' Z'"
[attr.opacity]="highlight() ? 0.5 : 0"
[attr.opacity]="
highlightKey()?.positionCodes?.includes(positionCode()) ? 0.5 : 0
"
/>
<svg:text
[attr.x]="textX()"
[attr.y]="textY()"
dominant-baseline="central"
text-anchor="middle"
font-size="80px"
fill="currentColor"
font-weight="lighter"
>
{{ keyLabel() }}
</svg:text>
@for (label of keyLabel(); track label.c) {
<svg:text
[attr.x]="textX()"
[attr.y]="textY()"
dominant-baseline="central"
text-anchor="middle"
font-size="80px"
fill="currentColor"
font-weight="lighter"
class="transition-opacity"
[attr.opacity]="
label.layer === highlightKey()?.layer &&
label.shiftKey === highlightKey()?.shiftKey &&
label.altGraphKey === highlightKey()?.altGraphKey
? 1
: 0
"
>
{{ label.c }}
</svg:text>
}
8 changes: 6 additions & 2 deletions src/app/components/switch-sector/switch-sector.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {
computed,
input,
} from '@angular/core';
import {
CharaChorderOneCharacterKey,
CharaChorderOneKeyLabel,
} from 'src/app/models/device-layout.models';

function sin(deg: number) {
return Math.sin((deg / 180) * Math.PI);
Expand All @@ -30,8 +34,8 @@ export class SwitchSectorComponent {
readonly direction = input.required<'cw' | 'ccw'>();
readonly degree = input.required<number>();
readonly positionCode = input.required<number>();
readonly keyLabel = input<string>('');
readonly highlight = input<boolean>(false);
readonly keyLabel = input<CharaChorderOneKeyLabel[]>([]);
readonly highlightKey = input<CharaChorderOneCharacterKey | null>(null);

readonly sectorPath = computed(() => {
const center = this.center();
Expand Down
4 changes: 1 addition & 3 deletions src/app/components/switch/switch.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
[direction]="rotationDirection()"
[positionCode]="positionCodeMap()[sector.direction]"
[keyLabel]="keyLabelMap()[positionCodeMap()[sector.direction]]"
[highlight]="
highlightPositionCodes().includes(positionCodeMap()[sector.direction])
"
[highlightKey]="highlightKey()"
></svg:g>
}
<svg:text
Expand Down
8 changes: 6 additions & 2 deletions src/app/components/switch/switch.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {
computed,
input,
} from '@angular/core';
import {
CharaChorderOneCharacterKey,
CharaChorderOneKeyLabel,
} from 'src/app/models/device-layout.models';
import { DirectionMap } from 'src/app/models/layout.models';
import { SwitchSectorComponent } from '../switch-sector/switch-sector.component';

Expand All @@ -27,8 +31,8 @@ export class SwitchComponent {
{ direction: 'w', degree: 180 },
];
readonly positionCodeMap = input.required<DirectionMap<number>>();
readonly keyLabelMap = input<Record<number, string>>({});
readonly highlightPositionCodes = input<number[]>([]);
readonly keyLabelMap = input<Record<number, CharaChorderOneKeyLabel[]>>({});
readonly highlightKey = input<CharaChorderOneCharacterKey | null>(null);
readonly r = computed(() => {
return (this.rotationDirection() === 'cw' ? 1 : -1) * this.rotation();
});
Expand Down
2 changes: 1 addition & 1 deletion src/app/data/topics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ export const SYMBOL_TOPIC: Topic = {
].map(generateCharacterLesson),
};

export const TOPICS = [NUMBER_TOPIC, LETTER_TOPIC];
export const TOPICS = [NUMBER_TOPIC, LETTER_TOPIC, SYMBOL_TOPIC];
13 changes: 10 additions & 3 deletions src/app/models/device-layout.models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,26 @@ export type DeviceLayout = CharaChorderOneLayout;

export enum CharaChorderOneLayer {
Primary = 'A1',
Secondary = 'A2', /* Numeric */
Tertiary = 'A3', /* Functional */
Secondary = 'A2' /* Numeric */,
Tertiary = 'A3' /* Functional */,
}

/*
* Key information of a character on CharaChorder One
*/
export interface CharaChorderOneCharacterKey {
device: 'CharaChorderOne',
device: 'CharaChorderOne';
positionCodes: number[];
layer: CharaChorderOneLayer;
shiftKey: boolean;
altGraphKey: boolean;
}

export interface CharaChorderOneKeyLabel {
c: string;
layer: CharaChorderOneLayer;
shiftKey: boolean;
altGraphKey: boolean;
}

export type CharacterDeviceKey = CharaChorderOneCharacterKey;
16 changes: 14 additions & 2 deletions src/app/pages/home-page/home-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,26 @@
[center]="{ x: 0, y: 0 }"
[rotationDirection]="'cw'"
[positionCodeMap]="{ c: 0, e: 1, n: 2, w: 3, s: 4 }"
[highlightPositionCodes]="highlightPositionCodes"
[highlightKey]="{
positionCodes: highlightPositionCodes,
device: 'CharaChorderOne',
layer: CharaChorderOneLayer.Primary,
shiftKey: false,
altGraphKey: false
}"
></g>
<g
appSwitch
[center]="{ x: 350, y: 350 }"
[rotationDirection]="'ccw'"
[positionCodeMap]="{ c: 5, e: 6, n: 7, w: 8, s: 9 }"
[highlightPositionCodes]="highlightPositionCodes"
[highlightKey]="{
positionCodes: highlightPositionCodes,
device: 'CharaChorderOne',
layer: CharaChorderOneLayer.Primary,
shiftKey: false,
altGraphKey: false
}"
></g>
</svg>
<main class="flex h-full flex-col items-center justify-center gap-4 p-4">
Expand Down
2 changes: 2 additions & 0 deletions src/app/pages/home-page/home-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Router, RouterLink } from '@angular/router';
import { HotkeysService } from '@ngneat/hotkeys';
import { Chance } from 'chance';
import { SwitchComponent } from 'src/app/components/switch/switch.component';
import { CharaChorderOneLayer } from 'src/app/models/device-layout.models';

const chance = new Chance();

Expand All @@ -35,6 +36,7 @@ export class HomePageComponent {
@HostBinding('class') classes = 'block relative h-full';

readonly hotkeysService = inject(HotkeysService);
readonly CharaChorderOneLayer = CharaChorderOneLayer;

ngOnInit() {
this.hotkeysService.addShortcut({ keys: 'space' }).subscribe(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/lesson-page/lesson-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<app-layout
class="block flex-1 overflow-hidden"
[keyLabelMap]="keyLabelMap()"
[highlightPositionCodes]="isFocus() ? highlightPositionCodes() : []"
[highlightKey]="isFocus() ? highlightKey() : null"
></app-layout>
<app-combo-counter
class="absolute bottom-4 left-4"
Expand Down
41 changes: 22 additions & 19 deletions src/app/pages/lesson-page/lesson-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { ComboCounterComponent } from 'src/app/components/combo-counter/combo-co
import { LayoutComponent } from 'src/app/components/layout/layout.component';
import { SpeedometerComponent } from 'src/app/components/speedometer/speedometer.component';
import { TOPICS } from 'src/app/data/topics';
import { CharaChorderOneKeyLabel } from 'src/app/models/device-layout.models';
import { Lesson, Topic } from 'src/app/models/topic.models';
import { DeviceLayoutStore } from 'src/app/stores/device-layout.store';
import { KeyboardLayoutStore } from 'src/app/stores/keyboard-layout.store';
Expand Down Expand Up @@ -162,33 +163,35 @@ export class LessonPageComponent implements OnInit, OnDestroy {
if (!lessonCharactersDevicePositionCodes) {
return {};
}
return Object.fromEntries(
lessonCharactersDevicePositionCodes
.map((v) =>
v?.characterDeviceKeys?.map(
({ positionCodes }) => [positionCodes[0], v.c] as const,
),
)
.filter(Boolean)
.flat() as [number, string][],
);
const keyLabelMap: Record<number, CharaChorderOneKeyLabel[]> = {};
lessonCharactersDevicePositionCodes.forEach((v) => {
v?.characterDeviceKeys?.forEach(
({ positionCodes, layer, shiftKey, altGraphKey }) => {
const positionCode = positionCodes[0];
const d = { c: v.c, layer, shiftKey, altGraphKey };
if (!keyLabelMap[positionCode]) {
keyLabelMap[positionCode] = [d];
} else {
keyLabelMap[positionCode].push(d);
}
},
);
});
return keyLabelMap;
});

readonly lessonStore = inject(LessonStore);
readonly highlightPositionCodes = computed(() => {
readonly highlightKey = computed(() => {
const currentCharacter = this.lessonStore.queue()[0];
const lessonCharactersDevicePositionCodes =
this.lessonCharactersDevicePositionCodes();
if (!lessonCharactersDevicePositionCodes) {
return [];
}
const positionCodes = lessonCharactersDevicePositionCodes.find(
const key = lessonCharactersDevicePositionCodes?.find(
(d) => d?.c === currentCharacter,
)?.characterDeviceKeys?.[0].positionCodes;
if (!positionCodes) {
return [];
)?.characterDeviceKeys?.[0];
if (!key) {
return null;
}
return positionCodes;
return key;
});

readonly hotkeys = inject(HotkeysService);
Expand Down

0 comments on commit 4e5ab23

Please sign in to comment.