Repository navigation
Expand file tree
/
Copy pathscript.js
More file actions
106 lines (94 loc) · 4.47 KB
/
Copy pathscript.js
File metadata and controls
106 lines (94 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const clock = document.querySelector('#clock');
const date = document.querySelector('#date');
const greeting = document.querySelector('#greeting');
const timezone = document.querySelector('#timezone');
const clockFormatButton = document.querySelector('#clock-format');
const copyTimeButton = document.querySelector('#copy-time');
const copyStatus = document.querySelector('#copy-status');
const profileDialog = document.querySelector('#profile-dialog');
const editProfileButton = document.querySelector('#edit-profile');
const closeDialogButton = document.querySelector('#close-dialog');
const profileForm = document.querySelector('#profile-form');
const profileLead = document.querySelector('#profile-lead');
const profileBio = document.querySelector('#profile-bio');
const leadInput = document.querySelector('#lead-input');
const bioInput = document.querySelector('#bio-input');
const resetProfileButton = document.querySelector('#reset-profile');
const settingsKey = 'lin-hung-cheng-page-settings';
const defaultProfile = {
lead: '我相信好的技術,始於對問題的耐心觀察。',
bio: '在研究所的學習中,我正深化人工智慧與資料處理的基礎,也持續練習把演算法與系統設計轉化為清晰、可靠的解決方案。希望未來能以資訊技術,為真實世界帶來一點有意義的改變。',
};
let is24Hour = true;
let lastTimestamp = '';
function getSettings() {
try { return JSON.parse(localStorage.getItem(settingsKey)) ?? {}; } catch { return {}; }
}
function saveSettings(settings) {
localStorage.setItem(settingsKey, JSON.stringify(settings));
}
function applyProfile(profile) {
profileLead.textContent = profile.lead;
profileBio.textContent = profile.bio;
}
function getTaipeiParts(now) {
return Object.fromEntries(new Intl.DateTimeFormat('en-GB', {
timeZone: 'Asia/Taipei', hour: '2-digit', minute: '2-digit', second: '2-digit', hourCycle: 'h23',
}).formatToParts(now).filter(({ type }) => type !== 'literal').map(({ type, value }) => [type, value]));
}
function updateClock() {
const now = new Date();
const parts = getTaipeiParts(now);
const time = new Intl.DateTimeFormat(is24Hour ? 'en-GB' : 'en-US', {
timeZone: 'Asia/Taipei', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: !is24Hour,
}).format(now).replace(/:/g, ' : ');
const day = new Intl.DateTimeFormat('zh-TW', {
timeZone: 'Asia/Taipei', year: 'numeric', month: 'long', day: 'numeric', weekday: 'long',
}).format(now);
clock.textContent = time;
clock.dateTime = now.toISOString();
date.textContent = day;
timezone.textContent = `UTC+08:00 · Asia/Taipei · ${Intl.DateTimeFormat().resolvedOptions().timeZone}`;
const hour = Number(parts.hour);
greeting.textContent = hour < 12 ? 'Good morning.' : hour < 18 ? 'Good afternoon.' : 'Good evening.';
lastTimestamp = `${now.toLocaleDateString('sv-SE', { timeZone: 'Asia/Taipei' })} ${parts.hour}:${parts.minute}:${parts.second} UTC+08:00`;
}
const savedSettings = getSettings();
is24Hour = savedSettings.is24Hour ?? true;
applyProfile({ ...defaultProfile, ...savedSettings.profile });
clockFormatButton.textContent = is24Hour ? '切換為 12H' : '切換為 24H';
clockFormatButton.setAttribute('aria-pressed', String(!is24Hour));
clockFormatButton.addEventListener('click', () => {
is24Hour = !is24Hour;
saveSettings({ ...getSettings(), is24Hour });
clockFormatButton.textContent = is24Hour ? '切換為 12H' : '切換為 24H';
clockFormatButton.setAttribute('aria-pressed', String(!is24Hour));
updateClock();
});
copyTimeButton.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(lastTimestamp);
copyStatus.textContent = `已複製:${lastTimestamp}`;
} catch {
copyStatus.textContent = '無法自動複製,請手動選取時間。';
}
});
editProfileButton.addEventListener('click', () => {
leadInput.value = profileLead.textContent;
bioInput.value = profileBio.textContent;
profileDialog.showModal();
});
closeDialogButton.addEventListener('click', () => profileDialog.close());
profileForm.addEventListener('submit', () => {
const profile = { lead: leadInput.value.trim(), bio: bioInput.value.trim() };
applyProfile(profile);
saveSettings({ ...getSettings(), profile });
});
resetProfileButton.addEventListener('click', () => {
applyProfile(defaultProfile);
saveSettings({ ...getSettings(), profile: defaultProfile });
leadInput.value = defaultProfile.lead;
bioInput.value = defaultProfile.bio;
});
updateClock();
setInterval(updateClock, 1000);