Files
soft_quay/app-win7/ui/gio/shell_detail.go
T

218 lines
6.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package gio
import (
"fmt"
"strings"
"gioui.org/layout"
"gioui.org/unit"
"gioui.org/widget/material"
"softbox.local/core/application"
)
const unsafeIconCacheMessage = "检测到不安全的图标缓存项。该缓存项未被使用,本次请求没有继续远端获取或自动修复。请完全退出 SoftBox 后,按故障排查文档由管理员人工处理。"
func (shell *AppShell) layoutDetail(
gtx layout.Context,
theme *material.Theme,
item application.CatalogListItem,
) layout.Dimensions {
shell.detailRendered = true
return panel(
gtx,
shellColors.muted,
unit.Dp(6),
layout.UniformInset(unit.Dp(12)),
func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(
gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Alignment: layout.Middle}.Layout(
gtx,
layout.Rigid(material.Body1(theme, "软件详情").Layout),
layout.Flexed(1, layout.Spacer{}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return shell.layoutFilterButton(
gtx,
theme,
&shell.closeDetail,
"关闭",
false,
)
}),
)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return shell.layoutUnsafeIconCacheFailure(gtx, theme, item.ID)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return shell.layoutAppIcon(
gtx,
theme,
item.ID,
item.Name,
unit.Dp(64),
unit.Dp(7),
)
})
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return layout.Center.Layout(gtx, material.Body1(theme, item.Name).Layout)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(3)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
label := material.Caption(
theme,
fmt.Sprintf("%s · %s", item.ID, item.Version),
)
label.Color = shellColors.secondary
return layout.Center.Layout(gtx, label.Layout)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return detailField(gtx, theme, "状态", statusLabel(item.Status))
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return detailField(gtx, theme, "分类", fallbackText(item.Category, "未分类"))
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return detailField(
gtx,
theme,
"标签",
fallbackText(strings.Join(item.Tags, " · "), "无"),
)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return detailField(
gtx,
theme,
"简介",
fallbackText(item.Description, "暂无简介"),
)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
if item.Reason == "" {
return layout.Dimensions{}
}
return detailField(gtx, theme, "不可用原因", reasonLabel(item.Reason))
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
if item.Tutorial == "" {
return layout.Dimensions{}
}
return detailField(gtx, theme, "教程", item.Tutorial)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
if item.Homepage == "" {
return layout.Dimensions{}
}
return detailField(gtx, theme, "主页", item.Homepage)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
label := material.Caption(theme, "实际安装/启动操作将在后续用例接入")
label.Color = shellColors.secondary
return label.Layout(gtx)
}),
)
},
)
}
func (shell *AppShell) layoutUnsafeIconCacheFailure(
gtx layout.Context,
theme *material.Theme,
appID string,
) layout.Dimensions {
failure, exists := shell.iconFailures[appID]
if !exists || failure.Code != application.IconFailureUnsafe ||
failure.Identity.AppID != appID {
return layout.Dimensions{}
}
return layout.Inset{Top: unit.Dp(8)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return outlinedPanel(
gtx,
shellColors.destructive,
shellColors.surface,
unit.Dp(6),
layout.UniformInset(unit.Dp(10)),
func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(
gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
title := material.Body1(theme, "图标缓存安全警告")
title.Color = shellColors.destructive
return title.Layout(gtx)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(3)}.Layout),
layout.Rigid(material.Body2(theme, unsafeIconCacheMessage).Layout),
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
diagnostic := material.Caption(theme, unsafeIconCacheDiagnostic(failure))
diagnostic.Color = shellColors.secondary
return diagnostic.Layout(gtx)
}),
)
},
)
})
}
func unsafeIconCacheDiagnostic(failure iconFailureState) string {
return fmt.Sprintf(
"诊断码:%s\n应用 ID:%s\n缓存定位符:%s",
failure.Code,
failure.Identity.AppID,
unsafeIconCacheLocator(failure.Identity),
)
}
func unsafeIconCacheLocator(identity application.IconEventIdentity) string {
digest := strings.TrimPrefix(identity.Reference, "sha256:")
return fmt.Sprintf("%s-%d.icon", digest, identity.DPI)
}
func detailField(
gtx layout.Context,
theme *material.Theme,
labelText string,
value string,
) layout.Dimensions {
return layout.Inset{Bottom: unit.Dp(8)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(
gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
label := material.Caption(theme, labelText)
label.Color = shellColors.secondary
return label.Layout(gtx)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(2)}.Layout),
layout.Rigid(material.Caption(theme, value).Layout),
)
})
}
func fallbackText(value, fallback string) string {
if value == "" {
return fallback
}
return value
}
func reasonLabel(reason string) string {
switch reason {
case "deprecated":
return "软件已停止发布"
case "minimum_os":
return "Windows 版本低于最低要求"
case "architecture":
return "没有当前架构的软件包"
default:
return reason
}
}