chore(release): v1.4.0

Shortcuts gain several bindings per action, mouse buttons and a searchable
picker, and the stored shortcut schema changes shape, so this is a minor bump.
Existing shortcuts migrate on first launch.

Play release notes state that this release carries no mobile feature changes;
the work is desktop-only.
This commit is contained in:
Yun Chan 2026-09-21 13:41:59 +09:00
parent 4ad1ae6ed4
commit 30d51c952f
25 changed files with 89 additions and 47 deletions

View file

@ -13,6 +13,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Cloud-optional backup (encrypted, opt-in)
- Plugin system for custom pipelines
## [1.4.0] - 2026-09-21
### Added
- **Several shortcuts per action.** Every action now holds a list of bindings
instead of a single one, so a second (or third) shortcut can be added with the
`+` button and removed individually.
- **Mouse buttons as shortcuts.** Side buttons (back / forward) can be bound on
their own; right and middle click require a modifier. Left click cannot be
bound because it drives every on-screen interaction. Mouse events cannot be
swallowed, so a bound button still performs its original action — the settings
screen says so before the binding is saved.
- **Pick a key from a searchable list.** Besides pressing the key, a shortcut can
now be chosen from a grouped dropdown with a search box inside it, which also
makes keys reachable that are awkward to press while recording.
- **The history and command popups are rebindable.** `Ctrl+Shift+V` and
`Ctrl+Shift+C` were fixed in code and had no settings entry; they are now
ordinary actions. The voice command shortcut, which had never been exposed in
settings, is visible as well.
### Fixed
- **Double-press hands-free never triggered.** Dictation and hands-free ship with
the same default key and are told apart by the double press, but shortcut
lookup stopped at the first match, so hands-free was unreachable in installed
builds. Both actions now receive the event and are split by press type.
- **Reserved system shortcuts could be assigned anyway.** The check compared
joined key names, so pressing the modifiers in a different order let `Ctrl+C`
and friends through. Combinations are now compared structurally.
- **Turning shortcuts off also killed the popup shortcuts permanently.** Disabling
global shortcuts released every registration in the process, including ones it
did not own, and re-enabling never restored them.
- **Enabling shortcuts after starting with them off left nothing bound.**
- **Shortcut labels were frozen in the language they were recorded in** and did not
follow the app language or platform conventions. They are now derived on display.
- **The dashboard caption indicator never reflected the real state** because the
event payload was stored instead of the state inside it.
### Changed
- Shortcuts are stored as one list per action. Existing shortcuts are migrated
automatically on first launch; no reconfiguration is needed.
## [1.3.7] - 2026-09-19
### Fixed

View file

@ -3,7 +3,7 @@
"info": {
"title": "D3RO-VOICE Admin API",
"description": "Admin CRM Edge Functions for user management, subscription CRUD, payment history, and audit logs.",
"version": "1.3.7"
"version": "1.4.0"
},
"servers": [
{

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/admin",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice Admin CRM — SaaS 관리 도구",
"scripts": {

View file

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Version>1.3.7</Version>
<Version>1.4.0</Version>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/desktop",
"version": "1.3.7",
"version": "1.4.0",
"productName": "d3ro-voice",
"description": "로컬 AI 음성 어시스턴트 (Electron)",
"main": "./out/main/index.js",

View file

@ -151,8 +151,8 @@ def versionSettingsValid = configuredVersionName != null &&
configuredVersionName ==~ strictSemver &&
configuredVersionCodeValue != null &&
configuredVersionCodeValue <= 2100000000L
def resolvedVersionName = versionSettingsValid ? configuredVersionName : "1.3.7"
def resolvedVersionCode = versionSettingsValid ? configuredVersionCodeValue.toInteger() : 1031007
def resolvedVersionName = versionSettingsValid ? configuredVersionName : "1.4.0"
def resolvedVersionCode = versionSettingsValid ? configuredVersionCodeValue.toInteger() : 1041000
def requiredReleaseSettings = [
D3RO_RELEASE_STORE_FILE: releaseStoreFilePath,

View file

@ -257,7 +257,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1031007;
CURRENT_PROJECT_VERSION = 1041000;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = D3ROVoice/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
@ -265,7 +265,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.3.7;
MARKETING_VERSION = 1.4.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -287,14 +287,14 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1031007;
CURRENT_PROJECT_VERSION = 1041000;
INFOPLIST_FILE = D3ROVoice/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.3.7;
MARKETING_VERSION = 1.4.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",

View file

@ -0,0 +1 @@
Maintenance update. This release focuses on keyboard shortcuts in the desktop app; there are no mobile feature changes.

View file

@ -0,0 +1 @@
유지보수 업데이트입니다. 이번 변경은 데스크톱 앱의 단축키 기능에 집중되어 있으며, 모바일 앱의 기능 변경은 없습니다.

View file

@ -1,12 +1,12 @@
{
"name": "@d3ro/mobile-rn",
"version": "1.3.7",
"version": "1.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@d3ro/mobile-rn",
"version": "1.3.7",
"version": "1.4.0",
"dependencies": {
"@d3ro/api-client": "file:../../packages/api-client",
"@d3ro/core": "file:../../packages/core",
@ -62,7 +62,7 @@
},
"../..": {
"name": "d3ro-voice-monorepo",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"workspaces": [
"apps/desktop",
@ -81,7 +81,7 @@
},
"../../packages/api-client": {
"name": "@d3ro/api-client",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"dependencies": {
"@d3ro/core": "*",
@ -98,7 +98,7 @@
},
"../../packages/core": {
"name": "@d3ro/core",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"dependencies": {
"docx": "^9.6.1"
@ -109,7 +109,7 @@
},
"../../packages/i18n": {
"name": "@d3ro/i18n",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"devDependencies": {
"@types/react": "^19.0.0"
@ -120,7 +120,7 @@
},
"../../packages/ui-native": {
"name": "@d3ro/ui-native",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"devDependencies": {
"@types/react": "*"

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/mobile-rn",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"scripts": {
"android": "react-native run-android",

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/web",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice 웹 앱 — Next.js 기반 SaaS 인터페이스",
"scripts": {

View file

@ -139,7 +139,7 @@ export function Sidebar(): React.ReactElement {
</PhosphorText>
</Box>
<Box sx={{ fontSize: '10px', fontFamily: 'ui-monospace, monospace', color: d3roPalette.text.muted }}>
v1.3.7
v1.4.0
</Box>
</Box>

View file

@ -4,10 +4,10 @@
// 설치 파일은 canonical Forgejo feed에서만 배포한다. 웹/사이트 빌드 산출물에는
// 설치 바이너리가 포함되지 않으므로 `/releases/...` 로컬 경로는 배포 환경에서 404다.
export const DESKTOP_VERSION = '1.3.7'
export const DESKTOP_VERSION = '1.4.0'
/** 릴리스 게시일. `release/product-version.json`의 releaseDate와 같아야 한다. */
export const DESKTOP_RELEASE_DATE = '2026-09-19'
export const DESKTOP_RELEASE_DATE = '2026-09-21'
const FORGEJO_ORIGIN = 'https://git.chanpaca.net'
const FORGEJO_OWNER = 'yunchan'

20
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "d3ro-voice-monorepo",
"version": "1.3.7",
"version": "1.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "d3ro-voice-monorepo",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"workspaces": [
"apps/desktop",
@ -25,7 +25,7 @@
},
"apps/admin": {
"name": "@d3ro/admin",
"version": "1.3.7",
"version": "1.4.0",
"dependencies": {
"@d3ro/api-client": "*",
"@d3ro/core": "*",
@ -109,7 +109,7 @@
},
"apps/desktop": {
"name": "@d3ro/desktop",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"dependencies": {
"@d3ro/core": "*",
@ -158,7 +158,7 @@
},
"apps/web": {
"name": "@d3ro/web",
"version": "1.3.7",
"version": "1.4.0",
"dependencies": {
"@d3ro/api-client": "*",
"@d3ro/core": "*",
@ -16861,7 +16861,7 @@
},
"packages/api-client": {
"name": "@d3ro/api-client",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"dependencies": {
"@d3ro/core": "*",
@ -16878,7 +16878,7 @@
},
"packages/core": {
"name": "@d3ro/core",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"dependencies": {
"docx": "^9.6.1"
@ -16889,7 +16889,7 @@
},
"packages/i18n": {
"name": "@d3ro/i18n",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"devDependencies": {
"@types/react": "^19.0.0"
@ -16900,7 +16900,7 @@
},
"packages/ui": {
"name": "@d3ro/ui",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"dependencies": {
"@d3ro/core": "*"
@ -16920,7 +16920,7 @@
},
"packages/ui-native": {
"name": "@d3ro/ui-native",
"version": "1.3.7",
"version": "1.4.0",
"license": "MIT",
"devDependencies": {
"@types/react": "*"

View file

@ -1,6 +1,6 @@
{
"name": "d3ro-voice-monorepo",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice — 멀티플랫폼 AI 음성 어시스턴트 (Monorepo)",
"author": "D3RO",

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/api-client",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice API 클라이언트 — Supabase 래퍼 (web/desktop/mobile 공유)",
"license": "MIT",

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/core",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice 공유 비즈니스 로직 — 타입, 에러, IPC 채널, 상수, 유틸",
"license": "MIT",

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/i18n",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice 공유 i18n — 12개 locale, 타입 안전 키, Context, 포맷 유틸",
"license": "MIT",

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/ui-native",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice React Native DS — MetalCard/PhosphorText/Led/WaveBars etc.",
"license": "MIT",

View file

@ -1,6 +1,6 @@
{
"name": "@d3ro/ui",
"version": "1.3.7",
"version": "1.4.0",
"private": true,
"description": "D3RO Voice 공유 UI — 디자인 시스템 컴포넌트 + 테마 토큰 + CSS 변수 맵",
"license": "MIT",

View file

@ -1,8 +1,8 @@
{
"schemaVersion": 1,
"version": "1.3.7",
"androidVersionCode": 1031007,
"iosBuildNumber": 1031007,
"releaseDate": "2026-09-19",
"version": "1.4.0",
"androidVersionCode": 1041000,
"iosBuildNumber": 1041000,
"releaseDate": "2026-09-21",
"desktopLicensePublicKeyId": "5c52b765135ee2531c681b53cd4dc0e96fff8737f496c0b04ba8334fc81a887f"
}

View file

@ -1,12 +1,12 @@
{
"name": "d3ro-voice-site",
"version": "1.3.7",
"version": "1.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "d3ro-voice-site",
"version": "1.3.7",
"version": "1.4.0",
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0"

View file

@ -1,7 +1,7 @@
{
"name": "d3ro-voice-site",
"private": true,
"version": "1.3.7",
"version": "1.4.0",
"type": "module",
"scripts": {
"dev": "vite --port 5199 --host",

View file

@ -5,10 +5,10 @@
// NAS 배포는 바이너리를 포함하지 않으므로 `/releases/...` 같은 로컬 경로는
// 실제 배포 환경에서 404가 된다.
export const DESKTOP_VERSION = '1.3.7'
export const DESKTOP_VERSION = '1.4.0'
/** 릴리스 게시일. `release/product-version.json`의 releaseDate와 같아야 한다. */
export const DESKTOP_RELEASE_DATE = '2026-09-19'
export const DESKTOP_RELEASE_DATE = '2026-09-21'
const FORGEJO_ORIGIN = 'https://git.chanpaca.net'
const FORGEJO_OWNER = 'yunchan'