TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Organizador de ventanas multicuenta para Dofus, nativo de macOS. Proyecto de fan, sin afiliación con Ankama — ver la investigación de mercado y las decisiones de arquitectura en research/market-research.md.README 전문 보기 ↗
Sitio web · Descargar última release
Organizador de ventanas multicuenta para Dofus, nativo de macOS. Proyecto de fan, sin afiliación con Ankama — ver la investigación de mercado y las decisiones de arquitectura en research/market-research.md.
.dmg — enlace directo o desde la página de la última release.DofusTabs a la carpeta Applications en la misma ventana..dmg (icono junto al nombre en Finder) y abre la app desde /Applications.DofusTabs.app → Abrir → confirmar en el diálogo. Solo hace falta esta vez; a partir de ahí abre normal con doble clic.La app te avisa sola cuando hay una versión nueva (al arrancar, y también desde "Buscar actualizaciones…" en el menú) — pero la descarga e instalación siguen siendo manuales: te lleva a la release en GitHub, repite el paso 1-4 desde ahí.
NSStatusItem, sin icono en el Dock)NSWorkspace)AXUIElement, no AppleScript)AXUIElementPerformAction + NSRunningApplication.activate)Cmd+1 (vía Carbon RegisterEventHotKey)Cmd+1...Cmd+9) sobre las ventanas activas (no excluidas), en un orden persistido en UserDefaultsCmd+,): reordenar personajes con ▲▼, excluir/incluir una ventana de la rotación de hotkeys, arrancar al iniciar sesión (SMAppService)Cmd+0 o "Organizar ventanas" en el menú/ajustes)scripts/generate-icon.swift, degradado morado→azul con símbolo de capas)Resources/{en,es,fr}.lproj, vía Bundle.module), con desplegable en Ajustes para forzar el idioma (AppLanguage + LanguagePreferenceStore) además del automático por sistema — el cambio pide reiniciar la app para aplicarse limpioNota: el auto-foco al cambiar de turno no hace falta construirlo — confirmado que el propio Dofus ya pone en primer plano la ventana del personaje activo cuando hay varias cuentas abiertas. Se descartó como diferenciador (ver §5.5 de la investigación, corregida).
Sin validar todavía (requiere probar con Dofus real abierto, varias cuentas):
parseCharacterName en DofusWindowManager.swift asume "Nombre - Clase - Version - Release", calcado del formato de Windows).WindowArranger) asume pantalla principal única; en multi-monitor solo organiza sobre NSScreen.screens.first..strings resultante (Bundle.module con defaultLocalization), pero no se ha confirmado visualmente abriendo el menú desplegable con el sistema en esos idiomas — se evitó automatizar clics cerca de una sesión de Dofus real abierta en ese momento.UpdateChecker: la lógica de comparación de versiones se verificó de forma aislada (sin red) y el chequeo real contra la v0.1.0 actual confirma que detecta correctamente "sin novedades" — pero no se ha visto en vivo el caso "hay versión nueva" dentro de la propia app (haría falta una release más nueva publicada para probarlo de verdad).# Compilar y correr directamente (debug, útil durante desarrollo)
swift run
# Compilar en release y empaquetar como DofusTabs.app
./scripts/build-app.sh
open .build/DofusTabs.app
# Generar el .dmg de distribución (instala create-dmg antes: brew install create-dmg)
./scripts/build-dmg.sh
scripts/build-dmg.sh deja el instalador en .build/DofusTabs-macos.dmg. Para publicarlo en GitHub Releases, sube dos copias: una con nombre versionado (para el archivo histórico) y otra con el nombre estable DofusTabs-macos.dmg (de la que depende el enlace de descarga directa de la web y del README, vía /releases/latest/download/DofusTabs-macos.dmg — si el nombre cambia, ese enlace se rompe):
cp .build/DofusTabs-macos.dmg .build/DofusTabs-X.Y.Z-macos.dmg
gh release upload vX.Y.Z .build/DofusTabs-macos.dmg .build/DofusTabs-X.Y.Z-macos.dmg
El icono de la app ya está generado y versionado (Resources/AppIcon.icns). Si quieres regenerarlo (cambiar colores/símbolo), edita scripts/generate-icon.swift y vuelve a correr:
swift scripts/generate-icon.swift
iconutil -c icns Resources/AppIcon.iconset -o Resources/AppIcon.icns
Las imágenes de producto se generan igual, con scripts/generate-promo-images.swift, y se escriben directamente en site/public/promo/ (fuente única — el README las referencia desde ahí):
readme-banner.png — el banner de la cabecera de este README.github-social-preview.png — para subir a mano en Settings → General → Social preview del repo de GitHub (no hay forma de automatizar esa subida por gh CLI).Landing page de una sola página en site/ (Astro + Tailwind v4), desplegada en Vercel: https://dofus-tabs-macos.vercel.app/. Cada push a main la redespliega sola (Vercel está conectado directamente al repo de GitHub, sin pasos manuales).
cd site
npm install # solo la primera vez
npm run dev # servidor local con recarga en caliente
npm run build # compila a site/dist — solo para probar el build en local, Vercel lo hace solo en cada push
Ajustes del proyecto en Vercel: Root Directory = site, resto (Framework Preset, Build/Output/Install Command) en automático — no hace falta tocar nada más ahí.
La web está en español (/), inglés (/en/) y francés (/fr/), con selector de idioma en la cabecera:
site/src/i18n/translations.ts — todo el texto de las 3 versiones, en un único diccionario tipado (SiteCopy). Es el único sitio donde se edita contenido.site/src/components/Site.astro — el layout/maquetación real, parametrizado por lang; no se toca para cambiar textos, solo estructura/estilos.site/src/pages/index.astro, en/index.astro, fr/index.astro — páginas finas, cada una solo instancia <Site lang="..." />.Para añadir un idioma nuevo a la web: añadir su entrada a languages/translations en translations.ts, y crear site/src/pages/<código>/index.astro igual que los existentes.
Los enlaces "Descargar"/"Ver el código"/"GitHub"/"Licencia MIT" de Site.astro apuntan al repo real (repoUrl al principio del componente) — si el repo cambia de sitio algún día, es la única línea que hay que tocar.
La primera vez, macOS pedirá un permiso en Ajustes del Sistema → Privacidad y Seguridad:
AXIsProcessTrustedWithOptions, se pide automáticamente al arrancar).Nota: al firmar en modo ad-hoc (
codesign --sign -), la identidad de firma cambia en cada build, así que macOS puede volver a pedir el permiso de Accesibilidad tras cada recompilación. Para desarrollo esto es solo una molestia menor; para distribución hará falta un Developer ID real (ver §5.6 de la investigación).
El arranque automático al iniciar sesión (
LaunchAtLoginManager, víaSMAppService) solo funciona de verdad ejecutando el.appempaquetado — bajoswift runfalla en silencio porque no hay un bundle real que registrar.
Los textos viven en Sources/DofusTabs/Resources/{en,es,fr}.lproj/Localizable.strings, centralizados por claves en Sources/DofusTabs/L10n.swift (nunca strings sueltos en el código). Por defecto macOS elige el idioma solo, según las preferencias de idioma del sistema (Ajustes → General → Idioma y región). Para añadir un idioma nuevo: crear el .lproj correspondiente, añadir sus claves, sumarlo a CFBundleLocalizations en Resources/Info.plist, y añadir el caso correspondiente a AppLanguage (ver más abajo).
NSAccessibilityUsageDescription (el texto del diálogo de permiso de Accesibilidad) se localiza aparte, con InfoPlist.strings por idioma en Resources/AppBundleLocalization/{en,es,fr}.lproj/ — es un mecanismo distinto al de Bundle.module, porque vive en el Info.plist del propio .app, no en el bundle de recursos de SwiftPM. scripts/build-app.sh copia ambos al empaquetar.
Importante: bajo swift run (modo desarrollo) sí funciona la localización de Bundle.module (Localizable.strings), pero el .app empaquetado es la única forma de probar InfoPlist.strings de verdad.
Desde Ajustes (Cmd+,) hay un desplegable "Idioma" con las 3 opciones más "Automático (idioma del sistema)". Al cambiarlo, AppLanguage.swift (LanguagePreferenceStore) guarda la elección en UserDefaults y pide reiniciar la app (botón "Reiniciar ahora" en el aviso, o más tarde a mano). Se pide reinicio a propósito: Bundle/NSBundle no ofrecen una forma fiable de "re-localizar en caliente" la UI ya construida (menú, ventana de Ajustes) sin arriesgar textos a medio cambiar.
Por qué L10n.swift no usa Bundle.module.preferredLocalizations directamente: ese mecanismo (el mismo que usan defaults write <bundle-id> AppleLanguages -array fr o -AppleLanguages por línea de comandos) resuelve el idioma vía kCFPreferencesCurrentApplication, que depende del bundleIdentifier real del proceso. Funciona bien en el .app empaquetado (tiene CFBundleIdentifier), pero bajo swift run el proceso no tiene bundle real (Bundle.main.bundleIdentifier == nil) y esa resolución automática ignora la preferencia guardada, cayendo directo al defaultLocalization del paquete — así que el desplegable "funcionaba" (guardaba la elección) pero no se notaba en el texto. La solución (L10n.localizedBundle) cuando hay un idioma forzado carga a mano el .lproj correspondiente dentro de Bundle.module en vez de fiarse de esa resolución automática, así que da igual si hay bundle real o no.
Para depurar sin pasar por el desplegable, sigue funcionando lo mismo de siempre (esto sí depende del bundleIdentifier, así que solo es fiable desde el .app empaquetado):
swift run DofusTabs -AppleLanguages '(fr)'
Package.swift — definición del paquete SPM (ejecutable, macOS 13+)
Sources/DofusTabs/
main.swift — punto de entrada, arranca NSApplication como .accessory
AppDelegate.swift — NSStatusItem, menú, hotkeys, ciclo de refresco, apertura de Ajustes
DofusWindowManager.swift — detección de procesos/ventanas Dofus vía AXUIElement, miniaturas, exclusión/orden
HotkeyManager.swift — registro de atajos globales vía Carbon RegisterEventHotKey (soporta varios a la vez)
CharacterOrderStore.swift — persiste el orden de personajes en UserDefaults para que Cmd+N sea estable entre sesiones
WindowRotationSettings.swift — persiste qué personajes están excluidos de la rotación de hotkeys
WindowArranger.swift — tileado de ventanas en cuadrícula sobre la pantalla principal
LaunchAtLoginManager.swift — envoltorio sobre SMAppService para arrancar al iniciar sesión
HotkeyBinding.swift — modelo tecla+modificadores, conversión NSEvent↔Carbon y formato para mostrar (ej. "⌘1")
HotkeyPreferencesStore.swift — persiste en UserDefaults la combinación asignada a cada atajo (ciclo, organizar, cada posición directa)
HotkeyRecorderView.swift — botón SwiftUI "clica y pulsa la tecla" para reasignar un atajo
SettingsView.swift — vista SwiftUI de la ventana de Ajustes
SettingsWindowController.swift — aloja SettingsView en una NSWindow normal de AppKit
FloatingPanelView.swift — contenido SwiftUI del panel flotante (lista de personajes + tirador de arrastre)
FloatingPanelController.swift — aloja FloatingPanelView en un NSPanel (.nonactivatingPanel, siempre encima, posición recordada)
UpdateChecker.swift — compara la versión instalada contra la última release de GitHub (API pública, sin autenticación)
NSImage+Rounded.swift — helper para redondear esquinas de las miniaturas
L10n.swift — acceso centralizado a las cadenas localizadas (Bundle.module)
AppLanguage.swift — desplegable de idioma: fuerza AppleLanguages y relanza la app
Resources/{en,es,fr}.lproj/ — Localizable.strings, recursos de SwiftPM (defaultLocalization: en)
Resources/
Info.plist — bundle info, LSUIElement=true (sin icono en Dock), CFBundleIconFile=AppIcon, CFBundleLocalizations
AppIcon.icns — icono de la app (versionado; AppIcon.iconset/ es intermedio y no se versiona)
AppBundleLocalization/{en,es,fr}.lproj/ — InfoPlist.strings (localiza NSAccessibilityUsageDescription)
scripts/
build-app.sh — compila en release y empaqueta el .app (firma ad-hoc, copia el icono)
build-dmg.sh — genera el instalador .dmg (requiere create-dmg) a partir del .app empaquetado
generate-icon.swift — genera el iconset/.icns a partir de un símbolo del sistema
generate-promo-images.swift — genera el banner del README y la imagen social de GitHub
research/market-research.md — investigación de mercado y decisiones de stack
site/ — landing page del proyecto (Astro + Tailwind v4), desplegada en Vercel
Todos son reasignables desde Ajustes (Cmd+,) — clic en el botón del atajo y pulsa la combinación que quieras (necesita al menos un modificador: ⌘/⌥/⌃/⇧, para no secuestrar una tecla normal del sistema).
| Atajo por defecto | Acción |
|---|---|
Cmd+1 | Ciclar a la siguiente ventana activa |
Cmd+1...Cmd+9 | Saltar directo al personaje en esa posición (según orden en Ajustes) |
Cmd+0 | Organizar/tilear todas las ventanas activas en pantalla |
Cmd+, (desde el menú) | Abrir Ajustes — este no es reasignable |
El panel flotante ("Panel flotante" en el menú) y la comprobación manual de actualizaciones ("Buscar actualizaciones…") no tienen atajo por defecto — solo se accede desde el menú, para no añadir más combinaciones de las necesarias.
/, /en/, /fr/), con selector en la cabeceraNSPanel, alternativa al menú desplegable): lista de personajes con número y atajo, clic para cambiar de ventana con el ratón; arrastrable a cualquier sitio de la pantalla (posición recordada entre sesiones) y se muestra/oculta desde "Panel flotante" en el menúUpdateChecker, sin Sparkle ni dependencias): compara la versión instalada contra la última release de GitHub. Chequeo silencioso al arrancar (solo añade un aviso al menú si hay algo nuevo) + "Buscar actualizaciones…" manual con confirmación explícita en los dos casos