Refine service information and simplify device controls
This commit is contained in:
@@ -23,7 +23,6 @@ import {
|
||||
ShieldCheck,
|
||||
ChevronDown,
|
||||
LoaderCircle,
|
||||
RefreshCw,
|
||||
ArrowDownLeft,
|
||||
CircleHelp,
|
||||
File as FileIcon,
|
||||
@@ -33,8 +32,11 @@ import {
|
||||
EllipsisVertical,
|
||||
Ellipsis,
|
||||
Info,
|
||||
MonitorSmartphone,
|
||||
Globe,
|
||||
} from '@lucide/vue';
|
||||
import QRCode from 'qrcode';
|
||||
import { version as appVersion } from '../package.json';
|
||||
import AccountPanel from './AccountPanel.vue';
|
||||
import SendComposer from './SendComposer.vue';
|
||||
import InstallButton from './InstallButton.vue';
|
||||
@@ -800,9 +802,6 @@ async function spaceAction(space, action, memberId) {
|
||||
{{ spaces.length ? '방 안의 기기' : '주변 기기' }}
|
||||
</h2>
|
||||
</div>
|
||||
<button class="icon-button" @click="act(refresh)" aria-label="기기 목록 새로고침">
|
||||
<RefreshCw :size="17" />
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="!connectionCards.length" class="empty-devices">
|
||||
<Monitor :size="30" stroke-width="1.4" />
|
||||
@@ -846,10 +845,10 @@ async function spaceAction(space, action, memberId) {
|
||||
>
|
||||
<span class="peer-top"
|
||||
><component :is="iconFor(card.peer.name)" :size="30" /><span
|
||||
v-if="card.pending"
|
||||
class="peer-live"
|
||||
:class="{ hasMenu: managedSpaces(card.peer.id).length }"
|
||||
><template v-if="card.pending">승인 대기</template
|
||||
><template v-else><i></i>온라인</template></span
|
||||
>승인 대기</span
|
||||
></span
|
||||
><strong>{{ deviceLabel(card.peer) }}</strong
|
||||
><span v-if="deviceDetail(card.peer)" class="peer-model">{{
|
||||
@@ -1130,13 +1129,38 @@ async function spaceAction(space, action, memberId) {
|
||||
</template>
|
||||
<template v-else-if="modal === 'about'">
|
||||
<div class="service-info">
|
||||
<strong>hop.</strong>
|
||||
<p>기기 사이를 가볍게.</p>
|
||||
<p>
|
||||
파일과 링크를 다른 기기로 보낼 수 있어요.<br />보관함에 저장한 자료는 최대 7일 후
|
||||
삭제됩니다.
|
||||
</p>
|
||||
<small>by noname.company</small>
|
||||
<strong class="service-brand">hop.</strong>
|
||||
<p class="service-tagline">기기 사이를 가볍게.</p>
|
||||
<div class="service-intro">
|
||||
<p>Android, iOS, macOS, Windows.</p>
|
||||
<p>서로 다른 운영체제에서도 파일과 링크를 자유롭게 주고받으세요.</p>
|
||||
</div>
|
||||
<ul class="service-features">
|
||||
<li>
|
||||
<MonitorSmartphone :size="20" aria-hidden="true" />
|
||||
<div>
|
||||
<strong>기기 구분 없이</strong>
|
||||
<p>스마트폰과 태블릿, PC를 자유롭게 연결</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<Globe :size="20" aria-hidden="true" />
|
||||
<div>
|
||||
<strong>설치 없이 간편하게</strong>
|
||||
<p>회원가입 없이 브라우저에서 바로 전송</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<QrCode :size="20" aria-hidden="true" />
|
||||
<div>
|
||||
<strong>네트워크가 달라도</strong>
|
||||
<p>QR 또는 초대 코드로 다른 기기와 연결</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<footer class="service-info-footer">
|
||||
<small>by noname.company</small><small>v{{ appVersion }}</small>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else
|
||||
|
||||
@@ -164,7 +164,7 @@ button:active:not(:disabled) {
|
||||
}
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
@@ -3252,7 +3252,12 @@ a.button {
|
||||
.modal .create-space {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
margin-top: 18px;
|
||||
gap: 14px;
|
||||
}
|
||||
.modal .join-form .modal-subtitle,
|
||||
.modal .create-space .modal-subtitle {
|
||||
margin: 0;
|
||||
}
|
||||
.modal .join-form input {
|
||||
width: 100%;
|
||||
@@ -3440,16 +3445,58 @@ a.button {
|
||||
.service-info {
|
||||
padding: 24px 0 4px;
|
||||
font-size: 13px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.service-info strong {
|
||||
.service-brand {
|
||||
font-size: 30px;
|
||||
letter-spacing: -0.07em;
|
||||
}
|
||||
.service-info p {
|
||||
margin: 12px 0;
|
||||
color: var(--muted);
|
||||
margin: 0;
|
||||
}
|
||||
.service-info small {
|
||||
.service-info .service-tagline {
|
||||
color: var(--muted);
|
||||
margin-top: 2px;
|
||||
}
|
||||
.service-intro {
|
||||
margin: 24px 0;
|
||||
}
|
||||
.service-intro p + p {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.service-features {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.service-features li {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.service-features svg {
|
||||
color: var(--muted);
|
||||
flex-shrink: 0;
|
||||
margin-top: 3px;
|
||||
}
|
||||
.service-features strong {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.service-features p {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
margin-top: 5px;
|
||||
}
|
||||
.service-info-footer {
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 18px;
|
||||
margin-top: 28px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -109,3 +109,7 @@
|
||||
- 최신 Docker 이미지 빌드 및 재시작 후 DB·파일·세션·미완료 분할 업로드 복구 검증 통과. NAS 원격 배포는 수행하지 않았다.
|
||||
|
||||
- 헤더 보조 기능은 로그인/보관함 뒤 더보기로 모았다. 메뉴의 앱 설치·테마·서비스 정보, 바깥 클릭/Escape 닫힘과 방향키 이동, 모바일 메뉴 경계를 검증했다. 메뉴가 닫혀도 설치 이벤트 수신을 유지해 PWA 설치 기능이 사라지지 않도록 했다.
|
||||
|
||||
- 서비스 정보는 hop. 제목을 유지하고 운영체제 설명과 아이콘 목록으로 정리했다. 제작사명은 왼쪽, 웹 패키지 버전(v0.1.0)은 오른쪽에 표시한다. PC·모바일 화면을 확인했다. 연결 참여/만들기 폼의 설명 여백과 간격을 줄이고 기기 카드의 온라인 표시는 제거했으며 승인 대기 표시는 유지했다.
|
||||
|
||||
- 기기 목록의 수동 새로고침 버튼을 제거했다. 접속 이벤트에 따른 목록 자동 갱신은 유지한다. 사용자가 수정한 헤더 버튼 간격과 서비스 정보 줄 간격도 함께 반영했다.
|
||||
|
||||
@@ -67,7 +67,7 @@ try {
|
||||
assert.equal(await guestCard.locator('.peer-card').isDisabled(), true);
|
||||
await guestCard.getByRole('button', { name: '외부 기기 기기 더보기' }).click();
|
||||
await guestCard.getByRole('menuitem', { name: '참여 승인', exact: true }).click();
|
||||
await guestCard.getByText('온라인', { exact: true }).waitFor();
|
||||
await guestCard.getByText('승인 대기', { exact: true }).waitFor({ state: 'hidden' });
|
||||
assert.equal(await guestCard.locator('.peer-card').isEnabled(), true);
|
||||
const hostCard = guest.locator('.peer-entry').filter({ hasText: '방장 Mac' });
|
||||
await hostCard.locator('.host-badge').waitFor();
|
||||
|
||||
@@ -65,6 +65,10 @@ try {
|
||||
await page.getByRole('menuitem', { name: '서비스 정보', exact: true }).click();
|
||||
await page.getByRole('dialog', { name: '서비스 정보', exact: true }).waitFor();
|
||||
assert.equal(await more.getAttribute('aria-expanded'), 'false');
|
||||
await page.screenshot({ path: 'tests/e2e/service-info-desktop.png' });
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await page.screenshot({ path: 'tests/e2e/service-info-mobile.png' });
|
||||
await page.setViewportSize({ width: 1280, height: 1000 });
|
||||
await page.getByRole('button', { name: '대화상자 닫기', exact: true }).click();
|
||||
|
||||
assert.equal(await page.getByText('어디로 보낼까요?', { exact: true }).count(), 0);
|
||||
@@ -288,6 +292,7 @@ try {
|
||||
await page.getByRole('button', { name: '연결 공간 만들기', exact: true }).click();
|
||||
await page.getByRole('checkbox', { name: '참여할 때 내 승인 받기' }).waitFor();
|
||||
assert.equal(await page.getByLabel('연결 코드', { exact: true }).count(), 0);
|
||||
await page.screenshot({ path: 'tests/e2e/connection-create-mobile.png' });
|
||||
await page.getByRole('button', { name: '만들기', exact: true }).click();
|
||||
assert.match(await page.locator('.invite-code').innerText(), /^[A-HJ-NP-Z2-9]{4}$/);
|
||||
assert.equal(await page.locator('.local-qr-note,.invite-display .spin').count(), 0);
|
||||
|
||||
Reference in New Issue
Block a user