mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 12:54:38 +03:00
Detail redesign round 2 bug fixes (#3990)
* increase full-width for measurement issue in apple devices * trade left margin for more full-width * removed isApple code from details page
This commit is contained in:
@@ -39,6 +39,7 @@ import { IUIConfig } from "./core/config";
|
||||
import { releaseNotes } from "./docs/en/ReleaseNotes";
|
||||
import { getPlatformURL } from "./core/createClient";
|
||||
import { lazyComponent } from "./utils/lazyComponent";
|
||||
import { isPlatformUniquelyRenderedByApple } from "./utils/apple";
|
||||
|
||||
const Performers = lazyComponent(
|
||||
() => import("./components/Performers/Performers")
|
||||
@@ -67,6 +68,8 @@ const SceneDuplicateChecker = lazyComponent(
|
||||
() => import("./components/SceneDuplicateChecker/SceneDuplicateChecker")
|
||||
);
|
||||
|
||||
const appleRendering = isPlatformUniquelyRenderedByApple();
|
||||
|
||||
initPolyfills();
|
||||
|
||||
MousetrapPause(Mousetrap);
|
||||
@@ -274,7 +277,11 @@ export const App: React.FC = () => {
|
||||
defaultTitle="Stash"
|
||||
/>
|
||||
{maybeRenderNavbar()}
|
||||
<div className="main container-fluid">
|
||||
<div
|
||||
className={`main container-fluid ${
|
||||
appleRendering ? "apple" : ""
|
||||
}`}
|
||||
>
|
||||
{renderContent()}
|
||||
</div>
|
||||
</InteractiveProvider>
|
||||
|
||||
@@ -35,7 +35,6 @@ import { ConfigurationContext } from "src/hooks/Config";
|
||||
import { IUIConfig } from "src/core/config";
|
||||
import ImageUtils from "src/utils/image";
|
||||
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||
import { isPlatformUniquelyRenderedByApple } from "src/utils/apple";
|
||||
|
||||
interface IProps {
|
||||
movie: GQL.MovieDataFragment;
|
||||
@@ -65,8 +64,6 @@ const MoviePage: React.FC<IProps> = ({ movie }) => {
|
||||
const [backImage, setBackImage] = useState<string | null>();
|
||||
const [encodingImage, setEncodingImage] = useState<boolean>(false);
|
||||
|
||||
const appleRendering = isPlatformUniquelyRenderedByApple();
|
||||
|
||||
const defaultImage =
|
||||
movie.front_image_path && movie.front_image_path.includes("default=true")
|
||||
? true
|
||||
@@ -417,7 +414,7 @@ const MoviePage: React.FC<IProps> = ({ movie }) => {
|
||||
<div
|
||||
className={`detail-header ${isEditing ? "edit" : ""} ${
|
||||
collapsed ? "collapsed" : !compactExpandedDetails ? "full-width" : ""
|
||||
} ${appleRendering ? "apple" : ""}`}
|
||||
}`}
|
||||
>
|
||||
{maybeRenderHeaderBackgroundImage()}
|
||||
<div className="detail-container">
|
||||
|
||||
@@ -64,6 +64,7 @@ export const CompressedMovieDetailsPanel: React.FC<IMovieDetailsPanel> = ({
|
||||
<a className="movie-name" onClick={() => scrollToTop()}>
|
||||
{movie.name}
|
||||
</a>
|
||||
<span className="detail-divider">/</span>
|
||||
{movie?.studio?.name ? (
|
||||
<span className="movie-studio">{movie?.studio?.name}</span>
|
||||
) : (
|
||||
|
||||
@@ -43,7 +43,6 @@ import { faInstagram, faTwitter } from "@fortawesome/free-brands-svg-icons";
|
||||
import { IUIConfig } from "src/core/config";
|
||||
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||
import ImageUtils from "src/utils/image";
|
||||
import { isPlatformUniquelyRenderedByApple } from "src/utils/apple";
|
||||
|
||||
interface IProps {
|
||||
performer: GQL.PerformerDataFragment;
|
||||
@@ -73,8 +72,6 @@ const PerformerPage: React.FC<IProps> = ({ performer }) => {
|
||||
const [encodingImage, setEncodingImage] = useState<boolean>(false);
|
||||
const [loadStickyHeader, setLoadStickyHeader] = useState<boolean>(false);
|
||||
|
||||
const appleRendering = isPlatformUniquelyRenderedByApple();
|
||||
|
||||
const activeImage = useMemo(() => {
|
||||
const performerImage = performer.image_path;
|
||||
if (isEditing) {
|
||||
@@ -549,7 +546,7 @@ const PerformerPage: React.FC<IProps> = ({ performer }) => {
|
||||
<div
|
||||
className={`detail-header ${isEditing ? "edit" : ""} ${
|
||||
collapsed ? "collapsed" : !compactExpandedDetails ? "full-width" : ""
|
||||
} ${appleRendering ? "apple" : ""}`}
|
||||
}`}
|
||||
>
|
||||
{maybeRenderHeaderBackgroundImage()}
|
||||
<div className="detail-container">
|
||||
|
||||
@@ -97,6 +97,21 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const formatAge = (birthdate?: string | null, deathdate?: string | null) => {
|
||||
if (!birthdate) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const age = TextUtils.age(birthdate, deathdate);
|
||||
|
||||
return (
|
||||
<span className="performer-age">
|
||||
<span className="age">{age}</span>
|
||||
<span className="birthdate"> ({birthdate})</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const formatWeight = (weight?: number | null) => {
|
||||
if (!weight) {
|
||||
return "";
|
||||
@@ -220,8 +235,16 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
||||
)}
|
||||
<DetailItem
|
||||
id="age"
|
||||
value={TextUtils.age(performer.birthdate, performer.death_date)}
|
||||
title={TextUtils.formatDate(intl, performer.birthdate ?? undefined)}
|
||||
value={
|
||||
!fullWidth
|
||||
? TextUtils.age(performer.birthdate, performer.death_date)
|
||||
: formatAge(performer.birthdate, performer.death_date)
|
||||
}
|
||||
title={
|
||||
!fullWidth
|
||||
? TextUtils.formatDate(intl, performer.birthdate ?? undefined)
|
||||
: ""
|
||||
}
|
||||
fullWidth={fullWidth}
|
||||
/>
|
||||
<DetailItem id="death_date" value={performer.death_date} />
|
||||
@@ -306,6 +329,7 @@ export const CompressedPerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
||||
<a className="performer-name" onClick={() => scrollToTop()}>
|
||||
{performer.name}
|
||||
</a>
|
||||
<span className="detail-divider">/</span>
|
||||
{performer.gender ? (
|
||||
<span className="performer-gender">
|
||||
{intl.formatMessage({ id: "gender_types." + performer.gender })}
|
||||
@@ -313,6 +337,7 @@ export const CompressedPerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<span className="detail-divider">/</span>
|
||||
{performer.birthdate ? (
|
||||
<span
|
||||
className="performer-age"
|
||||
@@ -323,6 +348,7 @@ export const CompressedPerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<span className="detail-divider">/</span>
|
||||
{performer.country ? (
|
||||
<span className="performer-country">
|
||||
<CountryFlag
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.col-md-8 .details-edit div:nth-last-child(2),
|
||||
.detail-header.edit .details-edit div:nth-last-child(2) {
|
||||
flex: 1;
|
||||
max-width: 100%;
|
||||
|
||||
@@ -42,7 +42,6 @@ import TextUtils from "src/utils/text";
|
||||
import { RatingSystem } from "src/components/Shared/Rating/RatingSystem";
|
||||
import ImageUtils from "src/utils/image";
|
||||
import { useRatingKeybinds } from "src/hooks/keybinds";
|
||||
import { isPlatformUniquelyRenderedByApple } from "src/utils/apple";
|
||||
|
||||
interface IProps {
|
||||
studio: GQL.StudioDataFragment;
|
||||
@@ -69,8 +68,6 @@ const StudioPage: React.FC<IProps> = ({ studio }) => {
|
||||
const [collapsed, setCollapsed] = useState<boolean>(!showAllDetails);
|
||||
const [loadStickyHeader, setLoadStickyHeader] = useState<boolean>(false);
|
||||
|
||||
const appleRendering = isPlatformUniquelyRenderedByApple();
|
||||
|
||||
// Editing state
|
||||
const [isEditing, setIsEditing] = useState<boolean>(false);
|
||||
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false);
|
||||
@@ -507,7 +504,7 @@ const StudioPage: React.FC<IProps> = ({ studio }) => {
|
||||
<div
|
||||
className={`detail-header ${isEditing ? "edit" : ""} ${
|
||||
collapsed ? "collapsed" : !compactExpandedDetails ? "full-width" : ""
|
||||
} ${appleRendering ? "apple" : ""}`}
|
||||
}`}
|
||||
>
|
||||
{maybeRenderHeaderBackgroundImage()}
|
||||
<div className="detail-container">
|
||||
|
||||
@@ -89,6 +89,7 @@ export const CompressedStudioDetailsPanel: React.FC<IStudioDetailsPanel> = ({
|
||||
<a className="studio-name" onClick={() => scrollToTop()}>
|
||||
{studio.name}
|
||||
</a>
|
||||
<span className="detail-divider">/</span>
|
||||
{studio?.parent_studio?.name ? (
|
||||
<span className="studio-parent">{studio?.parent_studio?.name}</span>
|
||||
) : (
|
||||
|
||||
@@ -38,7 +38,6 @@ import {
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { IUIConfig } from "src/core/config";
|
||||
import ImageUtils from "src/utils/image";
|
||||
import { isPlatformUniquelyRenderedByApple } from "src/utils/apple";
|
||||
|
||||
interface IProps {
|
||||
tag: GQL.TagDataFragment;
|
||||
@@ -64,8 +63,6 @@ const TagPage: React.FC<IProps> = ({ tag }) => {
|
||||
const [collapsed, setCollapsed] = useState<boolean>(!showAllDetails);
|
||||
const [loadStickyHeader, setLoadStickyHeader] = useState<boolean>(false);
|
||||
|
||||
const appleRendering = isPlatformUniquelyRenderedByApple();
|
||||
|
||||
const { tab = "scenes" } = useParams<ITabParams>();
|
||||
|
||||
// Editing state
|
||||
@@ -499,7 +496,7 @@ const TagPage: React.FC<IProps> = ({ tag }) => {
|
||||
<div
|
||||
className={`detail-header ${isEditing ? "edit" : ""} ${
|
||||
collapsed ? "collapsed" : !compactExpandedDetails ? "full-width" : ""
|
||||
} ${appleRendering ? "apple" : ""}`}
|
||||
}`}
|
||||
>
|
||||
{maybeRenderHeaderBackgroundImage()}
|
||||
<div className="detail-container">
|
||||
|
||||
@@ -79,6 +79,7 @@ export const CompressedTagDetailsPanel: React.FC<ITagDetails> = ({ tag }) => {
|
||||
<a className="tag-name" onClick={() => scrollToTop()}>
|
||||
{tag.name}
|
||||
</a>
|
||||
<span className="detail-divider">/</span>
|
||||
{tag.description ? (
|
||||
<span className="tag-desc">{tag.description}</span>
|
||||
) : (
|
||||
|
||||
@@ -69,26 +69,6 @@ dd {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.sticky.detail-header-group {
|
||||
padding: 1rem 2.5rem;
|
||||
|
||||
a.movie-name,
|
||||
a.performer-name,
|
||||
a.studio-name,
|
||||
a.tag-name {
|
||||
color: #f5f8fa;
|
||||
cursor: pointer;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
a,
|
||||
span {
|
||||
color: #d7d9db;
|
||||
font-weight: 600;
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sticky.detail-header {
|
||||
display: block;
|
||||
min-height: 50px;
|
||||
@@ -107,6 +87,32 @@ dd {
|
||||
.tag-name {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.sticky.detail-header-group {
|
||||
padding: 1rem 2.5rem;
|
||||
|
||||
a.movie-name,
|
||||
a.performer-name,
|
||||
a.studio-name,
|
||||
a.tag-name {
|
||||
color: #f5f8fa;
|
||||
cursor: pointer;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
a,
|
||||
span {
|
||||
color: #d7d9db;
|
||||
font-weight: 600;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.detail-divider {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail-expand-collapse {
|
||||
@@ -170,6 +176,11 @@ dd {
|
||||
border-bottom: 1px dotted #f5f8fa;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.performer-disambiguation {
|
||||
letter-spacing: -0.04rem;
|
||||
opacity: 0.65;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -195,7 +206,7 @@ dd {
|
||||
|
||||
.detail-header.edit {
|
||||
background-color: unset;
|
||||
overflow: auto;
|
||||
overflow: visible;
|
||||
|
||||
form {
|
||||
padding-top: 0.5rem;
|
||||
@@ -208,6 +219,11 @@ dd {
|
||||
.detail-header-image {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* StashID alignment fix */
|
||||
.form-group.row .row.no-gutters {
|
||||
padding-top: calc(0.375rem + 1px);
|
||||
}
|
||||
}
|
||||
|
||||
.detail-header.collapsed {
|
||||
@@ -255,14 +271,11 @@ dd {
|
||||
|
||||
.detail-item-title {
|
||||
display: table-cell;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.detail-item-value {
|
||||
margin-left: 1.5rem;
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.detail-item-value.age {
|
||||
border-bottom: unset;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
@@ -360,13 +373,21 @@ dd {
|
||||
|
||||
/* the .apple class denotes areas where rendering on some apple platforms has been inconsistent with other platforms
|
||||
these rules aim to address those inconsistences */
|
||||
.detail-header.apple .detail-container {
|
||||
display: flex;
|
||||
}
|
||||
.apple {
|
||||
.detail-header {
|
||||
.detail-container {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-header.full-width.apple .detail-header-image,
|
||||
.detail-header.edit.apple .detail-header-image {
|
||||
display: unset;
|
||||
.detail-header.edit .row {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.detail-header.full-width .detail-header-image,
|
||||
.detail-header.edit .detail-header-image {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-item-title {
|
||||
@@ -379,6 +400,13 @@ dd {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
white-space: pre-line;
|
||||
|
||||
.birthdate,
|
||||
.height-imperial,
|
||||
.penis-length-imperial,
|
||||
.weight-imperial {
|
||||
opacity: 0.65;
|
||||
}
|
||||
}
|
||||
|
||||
.input-control,
|
||||
|
||||
Reference in New Issue
Block a user