Refine launcher navigation and install list
This commit is contained in:
@@ -1073,15 +1073,22 @@ body, button {
|
||||
|
||||
/* Left hand side of the settings UI, for navigation. */
|
||||
#settingsContainerLeft {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 4%;
|
||||
height: 100%;
|
||||
width: 25%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.settingsTopActions {
|
||||
padding: 0 0 18px 24px;
|
||||
}
|
||||
|
||||
/* Settings navigation container. */
|
||||
#settingsNavContainer {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -2469,13 +2476,14 @@ input:checked + .toggleSwitchSlider:before {
|
||||
}
|
||||
#landingContainer > #upper > #content {
|
||||
display: inline-flex;
|
||||
width: 70%;
|
||||
width: 63%;
|
||||
height: 100%;
|
||||
}
|
||||
#landingContainer > #upper > #right {
|
||||
display: inline-flex;
|
||||
width: 15%;
|
||||
width: 22%;
|
||||
height: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* Lower content container. */
|
||||
@@ -2956,6 +2964,9 @@ input:checked + .toggleSwitchSlider:before {
|
||||
position: relative;
|
||||
top: 50px;
|
||||
align-items: flex-end;
|
||||
width: 100%;
|
||||
padding-right: 26px;
|
||||
box-sizing: border-box;
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
|
||||
@@ -2970,6 +2981,35 @@ input:checked + .toggleSwitchSlider:before {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#accountTriggerGroup {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
#accountPreviewText {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
#accountPreviewLabel {
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
color: rgba(255, 255, 255, 0.58);
|
||||
}
|
||||
|
||||
#accountPreviewName {
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
text-align: right;
|
||||
text-shadow: 0px 0px 18px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
#avatarMenuButton {
|
||||
padding: 0;
|
||||
border: none;
|
||||
@@ -2997,8 +3037,8 @@ input:checked + .toggleSwitchSlider:before {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
background-size: cover, 60%;
|
||||
}
|
||||
|
||||
#avatarMenuButton:hover #avatarContainer,
|
||||
@@ -4025,6 +4065,11 @@ input:checked + .toggleSwitchSlider:before {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.launcherPageTopBar {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.launcherPageHeader {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
@@ -4055,6 +4100,36 @@ input:checked + .toggleSwitchSlider:before {
|
||||
color: rgba(255, 255, 255, 0.74);
|
||||
}
|
||||
|
||||
.launcherBackButton {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
color: rgba(255, 255, 255, 0.88);
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.launcherBackButton::before {
|
||||
content: '←';
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.launcherBackButton:hover,
|
||||
.launcherBackButton:focus {
|
||||
color: #ffffff;
|
||||
text-shadow: 0px 0px 16px rgba(255, 255, 255, 0.45);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.launcherBackButton:active {
|
||||
color: rgba(255, 255, 255, 0.72);
|
||||
}
|
||||
|
||||
.launcherPageActions,
|
||||
.launcherCardActions,
|
||||
#landingNavButtons {
|
||||
@@ -4076,6 +4151,80 @@ input:checked + .toggleSwitchSlider:before {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.launcherListContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.launcherListItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 18px 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 18px;
|
||||
background: rgba(15, 15, 15, 0.56);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 18px 50px rgba(0, 0, 0, 0.18);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.launcherListItem[selected="true"] {
|
||||
border-color: rgba(253, 197, 78, 0.7);
|
||||
box-shadow: 0 22px 60px rgba(253, 197, 78, 0.14);
|
||||
}
|
||||
|
||||
.launcherListItemMain {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.launcherListTitleRow {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.launcherListTextGroup {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.launcherListTitle {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.launcherListMeta {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.launcherListDescription {
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
color: rgba(255, 255, 255, 0.76);
|
||||
}
|
||||
|
||||
.launcherListActions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.launcherCard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -140,7 +140,7 @@ function renderDetailPanel(profile){
|
||||
|
||||
function renderEmptyDetailPanel(){
|
||||
installDetailTitle.textContent = '프로필을 선택하세요'
|
||||
installDetailSummary.textContent = '왼쪽 목록에서 모드팩, 맵, 서버팩을 고르면 자세한 설명과 설치 조건을 볼 수 있습니다.'
|
||||
installDetailSummary.textContent = '아래 목록에서 모드팩, 맵, 서버팩을 고르면 자세한 설명과 설치 조건을 볼 수 있습니다.'
|
||||
installDetailMeta.innerHTML = ''
|
||||
installDetailInfo.innerHTML = ''
|
||||
installDetailBody.textContent = '관리자가 등록한 프로필 상세 설명이 여기에 표시됩니다.'
|
||||
@@ -183,24 +183,27 @@ async function renderInstallView(){
|
||||
}
|
||||
|
||||
for(const profile of catalog.profiles){
|
||||
const card = document.createElement('article')
|
||||
card.className = 'launcherCard'
|
||||
const row = document.createElement('article')
|
||||
row.className = 'launcherListItem'
|
||||
if(profile.id === selectedProfileId){
|
||||
card.setAttribute('selected', 'true')
|
||||
row.setAttribute('selected', 'true')
|
||||
}
|
||||
|
||||
const header = document.createElement('div')
|
||||
header.className = 'launcherCardHeader'
|
||||
const main = document.createElement('div')
|
||||
main.className = 'launcherListItemMain'
|
||||
|
||||
const titleGroup = document.createElement('div')
|
||||
titleGroup.className = 'launcherCardTitleGroup'
|
||||
const titleRow = document.createElement('div')
|
||||
titleRow.className = 'launcherListTitleRow'
|
||||
|
||||
const textGroup = document.createElement('div')
|
||||
textGroup.className = 'launcherListTextGroup'
|
||||
|
||||
const title = document.createElement('h3')
|
||||
title.className = 'launcherCardTitle'
|
||||
title.className = 'launcherListTitle'
|
||||
title.textContent = profile.name
|
||||
|
||||
const meta = document.createElement('div')
|
||||
meta.className = 'launcherCardMeta'
|
||||
meta.className = 'launcherListMeta'
|
||||
meta.appendChild(createInstallBadge(describeProfileKind(profile.kind)))
|
||||
if(installedIds.has(profile.id)){
|
||||
meta.appendChild(createInstallBadge('설치됨'))
|
||||
@@ -209,21 +212,20 @@ async function renderInstallView(){
|
||||
meta.appendChild(createInstallBadge('호스팅 가능'))
|
||||
}
|
||||
|
||||
titleGroup.appendChild(title)
|
||||
titleGroup.appendChild(meta)
|
||||
header.appendChild(titleGroup)
|
||||
textGroup.appendChild(title)
|
||||
|
||||
const description = document.createElement('p')
|
||||
description.className = 'launcherCardDescription'
|
||||
description.className = 'launcherListDescription'
|
||||
description.textContent = profile.description || '설명이 없습니다.'
|
||||
|
||||
const actions = document.createElement('div')
|
||||
actions.className = 'launcherCardActions'
|
||||
actions.className = 'launcherListActions'
|
||||
|
||||
const detailButton = document.createElement('button')
|
||||
detailButton.className = 'launcherSecondaryButton'
|
||||
detailButton.textContent = '자세히 보기'
|
||||
detailButton.addEventListener('click', () => {
|
||||
detailButton.addEventListener('click', (event) => {
|
||||
event.stopPropagation()
|
||||
selectProfile(profile.id)
|
||||
renderInstallView()
|
||||
})
|
||||
@@ -232,7 +234,8 @@ async function renderInstallView(){
|
||||
installButton.className = 'launcherPrimaryButton'
|
||||
installButton.textContent = installedIds.has(profile.id) ? '설치됨' : '라이브러리에 추가'
|
||||
installButton.disabled = installedIds.has(profile.id) || !profile.launchReady
|
||||
installButton.addEventListener('click', async () => {
|
||||
installButton.addEventListener('click', async (event) => {
|
||||
event.stopPropagation()
|
||||
try {
|
||||
const installedProfile = await CatalogManager.installProfile(profile.id)
|
||||
await ProfileAssetManager.prefetchProfileAssets(installedProfile)
|
||||
@@ -255,10 +258,17 @@ async function renderInstallView(){
|
||||
actions.appendChild(detailButton)
|
||||
actions.appendChild(installButton)
|
||||
|
||||
card.appendChild(header)
|
||||
card.appendChild(description)
|
||||
card.appendChild(actions)
|
||||
installCatalogList.appendChild(card)
|
||||
titleRow.appendChild(textGroup)
|
||||
titleRow.appendChild(meta)
|
||||
main.appendChild(titleRow)
|
||||
main.appendChild(description)
|
||||
row.appendChild(main)
|
||||
row.appendChild(actions)
|
||||
row.addEventListener('click', () => {
|
||||
selectProfile(profile.id)
|
||||
renderInstallView()
|
||||
})
|
||||
installCatalogList.appendChild(row)
|
||||
}
|
||||
|
||||
if(catalog.profiles.length === 0){
|
||||
@@ -289,6 +299,10 @@ document.getElementById('installOpenSettingsButton').addEventListener('click', a
|
||||
switchView(getCurrentView(), VIEWS.settings)
|
||||
})
|
||||
|
||||
document.getElementById('installBackButton').addEventListener('click', () => {
|
||||
switchView(getCurrentView(), VIEWS.landing)
|
||||
})
|
||||
|
||||
document.getElementById('installBackToLibraryButton').addEventListener('click', async () => {
|
||||
if(typeof refreshLibraryView === 'function'){
|
||||
await refreshLibraryView()
|
||||
|
||||
@@ -40,6 +40,7 @@ const launch_progress = document.getElementById('launch_progress')
|
||||
const launch_progress_label = document.getElementById('launch_progress_label')
|
||||
const launch_details_text = document.getElementById('launch_details_text')
|
||||
const server_selection_button = document.getElementById('server_selection_button')
|
||||
const accountPreviewName = document.getElementById('accountPreviewName')
|
||||
const avatarMenuButton = document.getElementById('avatarMenuButton')
|
||||
const avatarContainer = document.getElementById('avatarContainer')
|
||||
const accountMenu = document.getElementById('accountMenu')
|
||||
@@ -245,11 +246,12 @@ function updateSelectedAccount(authUser){
|
||||
username = authUser.displayName
|
||||
}
|
||||
if(authUser.uuid != null){
|
||||
avatarContainer.style.backgroundImage = `url('https://mc-heads.net/avatar/${authUser.uuid}/64')`
|
||||
avatarContainer.style.backgroundImage = `url('https://mc-heads.net/avatar/${authUser.uuid}/64'), url('assets/images/Icon.png')`
|
||||
}
|
||||
} else {
|
||||
avatarContainer.style.backgroundImage = `url('assets/images/Icon.png')`
|
||||
}
|
||||
accountPreviewName.textContent = username
|
||||
accountMenuName.textContent = username
|
||||
avatarMenuButton.disabled = authUser == null
|
||||
if(authUser == null){
|
||||
|
||||
@@ -394,6 +394,10 @@ document.getElementById('libraryOpenInstallButton').addEventListener('click', as
|
||||
switchView(getCurrentView(), VIEWS.install)
|
||||
})
|
||||
|
||||
document.getElementById('libraryBackButton').addEventListener('click', () => {
|
||||
switchView(getCurrentView(), VIEWS.landing)
|
||||
})
|
||||
|
||||
document.getElementById('libraryOpenSettingsButton').addEventListener('click', async () => {
|
||||
await prepareSettings()
|
||||
switchView(getCurrentView(), VIEWS.settings)
|
||||
|
||||
@@ -8,6 +8,7 @@ const {
|
||||
|
||||
const DropinModUtil = require('./assets/js/dropinmodutil')
|
||||
const { MSFT_OPCODE, MSFT_REPLY_TYPE, MSFT_ERROR } = require('./assets/js/ipcconstants')
|
||||
const settingsBackButton = document.getElementById('settingsBackButton')
|
||||
|
||||
const settingsState = {
|
||||
invalid: new Set()
|
||||
@@ -339,6 +340,11 @@ settingsNavDone.onclick = () => {
|
||||
switchView(getCurrentView(), VIEWS.library)
|
||||
}
|
||||
|
||||
settingsBackButton.onclick = () => {
|
||||
fullSettingsSave()
|
||||
switchView(getCurrentView(), VIEWS.landing)
|
||||
}
|
||||
|
||||
/**
|
||||
* Account Management Tab
|
||||
*/
|
||||
|
||||
@@ -12,10 +12,12 @@ mediaXURL = "#"
|
||||
mediaInstagramURL = "#"
|
||||
mediaYouTubeURL = "#"
|
||||
mediaDiscordURL = "https://discord.gg/Z8j6ahF4MJ"
|
||||
accountPreviewLabel = "계정"
|
||||
libraryButton = "라이브러리"
|
||||
installButton = "설치"
|
||||
|
||||
[ejs.settings]
|
||||
backButton = "메인으로"
|
||||
sourceGithubLink = "https://github.com/peunsu/MRSLauncher"
|
||||
supportLink = "https://github.com/peunsu/MRSLauncher/issues"
|
||||
|
||||
@@ -23,6 +25,7 @@ supportLink = "https://github.com/peunsu/MRSLauncher/issues"
|
||||
eyebrow = "Library"
|
||||
title = "내 라이브러리"
|
||||
subtitle = "설치한 프로필을 선택하고 바로 실행하거나, 서버 주소를 입력해 자동 접속을 준비할 수 있습니다."
|
||||
backButton = "메인으로"
|
||||
settingsButton = "설정"
|
||||
installPageButton = "설치 페이지"
|
||||
launchPageButton = "실행 화면"
|
||||
@@ -33,6 +36,7 @@ emptyDescription = "설치 페이지에서 네가 배포한 모드팩이나 서
|
||||
eyebrow = "Install"
|
||||
title = "설치 페이지"
|
||||
subtitle = "관리자가 미리 등록한 프로필을 둘러보고, 설명과 상세 내용을 확인한 뒤 내 라이브러리에 추가합니다."
|
||||
backButton = "메인으로"
|
||||
libraryPageButton = "라이브러리"
|
||||
notice = "설치 페이지는 읽기 전용 카탈로그입니다. 프로필 제목, 요약, 상세 설명은 관리자가 미리 등록하며, 클라이언트는 라이브러리에 추가만 할 수 있습니다."
|
||||
|
||||
|
||||
Reference in New Issue
Block a user