Merge branch 'main' into dev
This commit is contained in:
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@@ -7,21 +7,22 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- name: 🐧 Linux
|
- name: 🐧 Linux
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
pnpm-command: 'build:linux'
|
pnpm_command: 'build:linux'
|
||||||
binary_path: dist/*.deb
|
binary_path: dist/*.deb
|
||||||
asset_name: zeroone.deb
|
asset_name: zeroone.deb
|
||||||
- name: 🪟 Windows
|
- name: 🪟 Windows
|
||||||
os: windows-latest
|
os: macos-latest
|
||||||
pnpm-command: 'build:win'
|
pnpm_command: 'build:win'
|
||||||
binary_path: dist/*.exe
|
binary_path: dist/*.exe
|
||||||
asset_name: zeroone.exe
|
asset_name: zeroone.exe
|
||||||
- name: 🍏 Mac
|
- name: 🍏 Mac
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
pnpm-command: 'build:mac'
|
pnpm_command: 'build:mac'
|
||||||
binary_path: dist/*.dmg
|
binary_path: dist/*.dmg
|
||||||
asset_name: zeroone.dmg
|
asset_name: zeroone.dmg
|
||||||
name: ${{ matrix.name }} Release
|
name: ${{ matrix.name }} Release
|
||||||
@@ -29,7 +30,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: 🔢 Semantic Versioning
|
- name: 🔢 Semantic Versioning
|
||||||
id: version
|
id: version
|
||||||
uses: paulhatch/semantic-version@v5.3.0
|
uses: paulhatch/semantic-version@v5.4.0
|
||||||
with:
|
with:
|
||||||
tag_prefix: "v"
|
tag_prefix: "v"
|
||||||
bump_each_commit: true
|
bump_each_commit: true
|
||||||
@@ -50,7 +51,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
pnpm i
|
pnpm i
|
||||||
pnpm ${{ matrix.pnpm-command }}
|
pnpm ${{ matrix.pnpm_command }}
|
||||||
|
|
||||||
- name: 📦 Release binary
|
- name: 📦 Release binary
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
"packageManager": "pnpm@8.14.1",
|
"packageManager": "pnpm@8.14.1",
|
||||||
"homepage": "https://github.com/katbinaris/zeroone",
|
"homepage": "https://github.com/katbinaris/zeroone",
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "io.binaris.zeroone",
|
|
||||||
"productName": "ZERO_ONE"
|
"productName": "ZERO_ONE"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ export const useAppStore = defineStore('app', {
|
|||||||
},
|
},
|
||||||
previewDeviceModel: localStorage.getItem('previewDeviceModel') || 'nanoOne',
|
previewDeviceModel: localStorage.getItem('previewDeviceModel') || 'nanoOne',
|
||||||
profileManagerDragging: false,
|
profileManagerDragging: false,
|
||||||
showProfileConfig: false
|
showProfileConfig: false,
|
||||||
|
selectOnInput: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
@@ -76,6 +77,9 @@ export const useAppStore = defineStore('app', {
|
|||||||
setShowProfileConfig(show) {
|
setShowProfileConfig(show) {
|
||||||
show = false // TODO: Remove this / replace with actual logic
|
show = false // TODO: Remove this / replace with actual logic
|
||||||
this.showProfileConfig = show
|
this.showProfileConfig = show
|
||||||
|
},
|
||||||
|
toggleSelectOnInput() {
|
||||||
|
this.selectOnInput = !this.selectOnInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<ScrambleText ref="title" :text="$t(page.titleKey)" />
|
<ScrambleText ref="title" :text="$t(page.titleKey)" />
|
||||||
</template>
|
</template>
|
||||||
</TabSelect>
|
</TabSelect>
|
||||||
<div class="grow overflow-y-auto">
|
<div :key="deviceStore.currentProfileName" class="grow overflow-y-auto">
|
||||||
<component :is="appStore.currentConfigComponent" />
|
<component :is="appStore.currentConfigComponent" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
:actions="heldActions"
|
:actions="heldActions"
|
||||||
class="p-2"
|
class="p-2"
|
||||||
@add="deviceStore.addKeyAction(null, appStore.selectedKey, 2)"
|
@add="deviceStore.addKeyAction(null, appStore.selectedKey, 2)"
|
||||||
@delete="(index) => deviceStore.removeKeyAction(index, appStore.selectedKey, 3)"
|
@delete="(index) => deviceStore.removeKeyAction(index, appStore.selectedKey, 2)"
|
||||||
/>
|
/>
|
||||||
</ConfigSection>
|
</ConfigSection>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -20,6 +20,16 @@
|
|||||||
<Input v-model="valueMaxInput" class="my-2" type="number" />
|
<Input v-model="valueMaxInput" class="my-2" type="number" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<div class="flex-1">
|
||||||
|
<span class="font-mono text-sm text-muted-foreground">Total Detents:</span>
|
||||||
|
<Input v-model="totalDetentsInput" class="my-2" type="number" />
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<span class="font-mono text-sm text-muted-foreground">Detents/Rotation:</span>
|
||||||
|
<Input v-model="detentsPerRotationInput" class="my-2" type="number" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -37,6 +47,8 @@ const ccInput = ref(props.value.cc)
|
|||||||
const channelInput = ref(props.value.channel)
|
const channelInput = ref(props.value.channel)
|
||||||
const valueMinInput = ref(props.value.valueMin)
|
const valueMinInput = ref(props.value.valueMin)
|
||||||
const valueMaxInput = ref(props.value.valueMax)
|
const valueMaxInput = ref(props.value.valueMax)
|
||||||
|
const totalDetentsInput = ref(props.value.haptic.endPos)
|
||||||
|
const detentsPerRotationInput = ref(props.value.haptic.detentCount)
|
||||||
|
|
||||||
watch(ccInput, (cc) => {
|
watch(ccInput, (cc) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -65,4 +77,18 @@ watch(valueMaxInput, (valueMax) => {
|
|||||||
})
|
})
|
||||||
emit('update', { valueMax: valueMaxInput.value })
|
emit('update', { valueMax: valueMaxInput.value })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(totalDetentsInput, (totalDetents) => {
|
||||||
|
nextTick(() => {
|
||||||
|
totalDetentsInput.value = Math.max(0, Math.min(Number(totalDetents), 9999))
|
||||||
|
})
|
||||||
|
emit('update', { haptic: { endPos: totalDetents } })
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(detentsPerRotationInput, (detentsPerRotation) => {
|
||||||
|
nextTick(() => {
|
||||||
|
detentsPerRotationInput.value = Math.max(0, Math.min(Number(detentsPerRotation), 9999))
|
||||||
|
})
|
||||||
|
emit('update', { haptic: { detentCount: detentsPerRotation } })
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -45,15 +45,15 @@
|
|||||||
</MenubarTrigger>
|
</MenubarTrigger>
|
||||||
<MenubarContent>
|
<MenubarContent>
|
||||||
<!-- TODO: Switch keyboard shortcut icons based on platform -->
|
<!-- TODO: Switch keyboard shortcut icons based on platform -->
|
||||||
<MenubarItem @click="deviceStore.setConnected(!deviceStore.connected)">
|
<MenubarItem v-if="false" @click="deviceStore.setConnected(!deviceStore.connected)">
|
||||||
{{
|
{{
|
||||||
deviceStore.connected ? $t('navbar.device.disconnect') : $t('navbar.device.connect')
|
deviceStore.connected ? $t('navbar.device.disconnect') : $t('navbar.device.connect')
|
||||||
}}
|
}}
|
||||||
<MenubarShortcut>⌘D</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘D</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarItem v-if="deviceStore.attachedDeviceIds.length > 1"
|
<MenubarItem v-if="deviceStore.attachedDeviceIds.length > 1"
|
||||||
>Next Device
|
>Next Device
|
||||||
<MenubarShortcut>⌘N</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘N</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarSeparator />
|
<MenubarSeparator />
|
||||||
<MenubarItem class="flex justify-between" @click="deviceStore.cycleOrientation">
|
<MenubarItem class="flex justify-between" @click="deviceStore.cycleOrientation">
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<p>
|
<p>
|
||||||
{{ deviceStore.orientationLabels[deviceStore.settings?.deviceOrientation || 0] }}°
|
{{ deviceStore.orientationLabels[deviceStore.settings?.deviceOrientation || 0] }}°
|
||||||
</p>
|
</p>
|
||||||
<MenubarShortcut>⌘R</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘R</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarItem class="flex justify-between" @click="deviceStore.cycleIdleTimeout">
|
<MenubarItem class="flex justify-between" @click="deviceStore.cycleIdleTimeout">
|
||||||
<p>Idle Timeout: </p>
|
<p>Idle Timeout: </p>
|
||||||
@@ -72,27 +72,32 @@
|
|||||||
: 'Off'
|
: 'Off'
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
<MenubarShortcut>⌘T</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘T</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarSeparator />
|
<MenubarSeparator />
|
||||||
<MenubarItem class="flex justify-between" @click="appStore.switchPreviewDeviceModel">
|
<MenubarItem class="flex justify-between" @click="appStore.switchPreviewDeviceModel">
|
||||||
<p>Skin: </p>
|
<p>Skin: </p>
|
||||||
<p>{{ previewDeviceNames[appStore.previewDeviceModel || 'nanoOne'] }}</p>
|
<p>{{ previewDeviceNames[appStore.previewDeviceModel || 'nanoOne'] }}</p>
|
||||||
<MenubarShortcut>⌘S</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘S</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarSeparator />
|
<MenubarItem class="flex justify-between" @click="appStore.toggleSelectOnInput">
|
||||||
<MenubarItem
|
<p>Auto Select: </p>
|
||||||
|
<p>{{ appStore.selectOnInput ? 'On' : 'Off' }}</p>
|
||||||
|
<MenubarShortcut v-if="showShortcuts">⌘K</MenubarShortcut>
|
||||||
|
</MenubarItem>
|
||||||
|
<MenubarSeparator v-if="false" />
|
||||||
|
<MenubarItem v-if="false"
|
||||||
>{{ $t('navbar.device.export') }}
|
>{{ $t('navbar.device.export') }}
|
||||||
<MenubarShortcut>⌘E</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘E</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarItem
|
<MenubarItem v-if="false"
|
||||||
>{{ $t('navbar.device.import') }}
|
>{{ $t('navbar.device.import') }}
|
||||||
<MenubarShortcut>⌘I</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘I</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarSeparator />
|
<MenubarSeparator v-if="false" />
|
||||||
<MenubarItem
|
<MenubarItem v-if="false"
|
||||||
>{{ $t('navbar.device.quit') }}
|
>{{ $t('navbar.device.quit') }}
|
||||||
<MenubarShortcut>⌘Q</MenubarShortcut>
|
<MenubarShortcut v-if="showShortcuts">⌘Q</MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarContent>
|
</MenubarContent>
|
||||||
</MenubarMenu>
|
</MenubarMenu>
|
||||||
@@ -149,7 +154,7 @@
|
|||||||
<div v-if="deviceStore.dirtyState" class="text-sm">
|
<div v-if="deviceStore.dirtyState" class="text-sm">
|
||||||
<PenLine class="inline-block h-4" />Unsaved Changes
|
<PenLine class="inline-block h-4" />Unsaved Changes
|
||||||
</div>
|
</div>
|
||||||
<MenubarButton class="app-titlebar-button border-2"> Revert </MenubarButton>
|
<MenubarButton v-if="false" class="app-titlebar-button border-2"> Revert </MenubarButton>
|
||||||
<MenubarButton
|
<MenubarButton
|
||||||
:class="
|
:class="
|
||||||
deviceStore.dirtyState
|
deviceStore.dirtyState
|
||||||
@@ -220,6 +225,7 @@ const deviceStore = useDeviceStore()
|
|||||||
const minimizable = ref(true)
|
const minimizable = ref(true)
|
||||||
const maximizable = ref(true)
|
const maximizable = ref(true)
|
||||||
const showDisconnectButton = ref(false)
|
const showDisconnectButton = ref(false)
|
||||||
|
const showShortcuts = ref(false)
|
||||||
|
|
||||||
const isMaximized = ref(false)
|
const isMaximized = ref(false)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<Collapsible v-model:open="expanded" :default-open="true">
|
<Collapsible v-model:open="expanded" :default-open="true">
|
||||||
<!-- TODO: Make profile groups computed instead defining them of using v-for -->
|
<!-- TODO: Make profile groups computed instead defining them of using v-for -->
|
||||||
<div
|
<div
|
||||||
|
v-if="false"
|
||||||
class="group flex h-12 w-full items-center justify-between border-0 border-b bg-zinc-900 py-2 text-left text-sm text-muted-foreground"
|
class="group flex h-12 w-full items-center justify-between border-0 border-b bg-zinc-900 py-2 text-left text-sm text-muted-foreground"
|
||||||
>
|
>
|
||||||
<CollapsibleTrigger class="group flex min-w-0 items-center gap-2">
|
<CollapsibleTrigger class="group flex min-w-0 items-center gap-2">
|
||||||
|
|||||||
@@ -41,7 +41,16 @@
|
|||||||
<X class="h-5" />
|
<X class="h-5" />
|
||||||
</button>
|
</button>
|
||||||
</Transition>
|
</Transition>
|
||||||
<DropdownMenu>
|
<Transition name="fade">
|
||||||
|
<button
|
||||||
|
v-if="!appStore.showProfileConfig"
|
||||||
|
class="flex aspect-square h-8 items-center justify-center rounded-lg border border-zinc-100 bg-zinc-300 text-black hover:bg-zinc-200"
|
||||||
|
@click="deviceStore.createProfile"
|
||||||
|
>
|
||||||
|
<Plus class="h-4" />
|
||||||
|
</button>
|
||||||
|
</Transition>
|
||||||
|
<DropdownMenu v-if="false">
|
||||||
<DropdownMenuTrigger>
|
<DropdownMenuTrigger>
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<button
|
<button
|
||||||
@@ -54,7 +63,7 @@
|
|||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
<DropdownMenuItem @click="deviceStore.createProfile"> Profile </DropdownMenuItem>
|
<DropdownMenuItem @click="deviceStore.createProfile"> Profile </DropdownMenuItem>
|
||||||
<DropdownMenuItem> Category </DropdownMenuItem>
|
<DropdownMenuItem v-if="false"> Category </DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
@@ -134,7 +143,7 @@ const dragOptions = ref({
|
|||||||
direction: 'vertical'
|
direction: 'vertical'
|
||||||
})
|
})
|
||||||
|
|
||||||
const maxProfiles = 32
|
const maxProfiles = 10
|
||||||
|
|
||||||
const renderProfileConfig = ref(appStore.showProfileConfig)
|
const renderProfileConfig = ref(appStore.showProfileConfig)
|
||||||
const renderProfileList = ref(!appStore.showProfileConfig)
|
const renderProfileList = ref(!appStore.showProfileConfig)
|
||||||
|
|||||||
@@ -703,12 +703,12 @@ export const initializeDevices = () => {
|
|||||||
}
|
}
|
||||||
if (update.p !== undefined) {
|
if (update.p !== undefined) {
|
||||||
deviceStore.setPosition(update.p)
|
deviceStore.setPosition(update.p)
|
||||||
appStore.selectConfigFeature('knob')
|
if (appStore.selectOnInput) appStore.selectConfigFeature('knob')
|
||||||
}
|
}
|
||||||
if (update.kd !== undefined) {
|
if (update.kd !== undefined) {
|
||||||
const keyLabel = deviceStore.keyLabels[update.kd]
|
const keyLabel = deviceStore.keyLabels[update.kd]
|
||||||
deviceStore.keyStates[keyLabel] = true
|
deviceStore.keyStates[keyLabel] = true
|
||||||
appStore.selectKey(keyLabel)
|
if (appStore.selectOnInput) appStore.selectKey(keyLabel)
|
||||||
}
|
}
|
||||||
if (update.ku !== undefined) {
|
if (update.ku !== undefined) {
|
||||||
deviceStore.keyStates[deviceStore.keyLabels[update.ku]] = false
|
deviceStore.keyStates[deviceStore.keyLabels[update.ku]] = false
|
||||||
|
|||||||
Reference in New Issue
Block a user