mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-09 16:06:21 +02:00
add fork in header
This commit is contained in:
@ -128,6 +128,9 @@ export function Icons() {
|
|||||||
<symbol id="check-circle" viewBox="0 0 24 24">
|
<symbol id="check-circle" viewBox="0 0 24 24">
|
||||||
<path d="M12 2C6.5 2 2 6.5 2 12S6.5 22 12 22 22 17.5 22 12 17.5 2 12 2M10 17L5 12L6.41 10.59L10 14.17L17.59 6.58L19 8L10 17Z" />
|
<path d="M12 2C6.5 2 2 6.5 2 12S6.5 22 12 22 22 17.5 22 12 17.5 2 12 2M10 17L5 12L6.41 10.59L10 14.17L17.59 6.58L19 8L10 17Z" />
|
||||||
</symbol>
|
</symbol>
|
||||||
|
<symbol id="fork" viewBox="0 0 24 24">
|
||||||
|
<path d="M13 14c-3.36 0-4.46 1.35-4.82 2.24C9.25 16.7 10 17.76 10 19a3 3 0 0 1-3 3 3 3 0 0 1-3-3c0-1.31.83-2.42 2-2.83V7.83A2.99 2.99 0 0 1 4 5a3 3 0 0 1 3-3 3 3 0 0 1 3 3c0 1.31-.83 2.42-2 2.83v5.29c.88-.65 2.16-1.12 4-1.12 2.67 0 3.56-1.34 3.85-2.23A3.006 3.006 0 0 1 14 7a3 3 0 0 1 3-3 3 3 0 0 1 3 3c0 1.34-.88 2.5-2.09 2.86C17.65 11.29 16.68 14 13 14m-6 4a1 1 0 0 0-1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1M7 4a1 1 0 0 0-1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1m10 2a1 1 0 0 0-1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1Z" />
|
||||||
|
</symbol>
|
||||||
<symbol id="loader-icon" viewBox="0 0 44 44">
|
<symbol id="loader-icon" viewBox="0 0 44 44">
|
||||||
{/* By Sam Herbert (@sherb), for everyone. More http://goo.gl/7AJzbL */}
|
{/* By Sam Herbert (@sherb), for everyone. More http://goo.gl/7AJzbL */}
|
||||||
<g fill="none" fillRule="evenodd" strokeWidth={10}>
|
<g fill="none" fillRule="evenodd" strokeWidth={10}>
|
||||||
|
@ -4,16 +4,30 @@ import { Trans, NumberFormat, t } from '@lingui/macro';
|
|||||||
import { I18n } from '@lingui/react';
|
import { I18n } from '@lingui/react';
|
||||||
import { ProBadge } from './ProBadge';
|
import { ProBadge } from './ProBadge';
|
||||||
import { HStack, Stack } from './Stack';
|
import { HStack, Stack } from './Stack';
|
||||||
|
import { Icon } from './Icons';
|
||||||
|
|
||||||
const DEFAULT_PROFILE_IMG =
|
const DEFAULT_PROFILE_IMG =
|
||||||
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23ccc' d='M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z'/%3E%3C/svg%3E";
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23ccc' d='M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z'/%3E%3C/svg%3E";
|
||||||
|
|
||||||
export function MainHeader(props) {
|
export function MainHeader({
|
||||||
|
user,
|
||||||
|
currentItem,
|
||||||
|
titleInputBlurHandler,
|
||||||
|
runBtnClickHandler,
|
||||||
|
assetsBtnHandler,
|
||||||
|
isFileMode,
|
||||||
|
onItemFork,
|
||||||
|
...props
|
||||||
|
}) {
|
||||||
const isAutoPreviewOn =
|
const isAutoPreviewOn =
|
||||||
window.forcedSettings.autoPreview !== undefined
|
window.forcedSettings.autoPreview !== undefined
|
||||||
? window.forcedSettings
|
? window.forcedSettings
|
||||||
: props.isAutoPreviewOn;
|
: props.isAutoPreviewOn;
|
||||||
|
|
||||||
|
const isNotMine =
|
||||||
|
currentItem.createdBy && user?.uid !== currentItem.createdBy;
|
||||||
|
|
||||||
|
// console.log(33, currentItem, user?.uid);
|
||||||
return (
|
return (
|
||||||
<I18n>
|
<I18n>
|
||||||
{({ i18n }) => (
|
{({ i18n }) => (
|
||||||
@ -23,15 +37,15 @@ export function MainHeader(props) {
|
|||||||
id="titleInput"
|
id="titleInput"
|
||||||
title="Click to edit"
|
title="Click to edit"
|
||||||
class="item-title-input"
|
class="item-title-input"
|
||||||
value={props.currentItem.title}
|
value={currentItem.title}
|
||||||
onBlur={props.titleInputBlurHandler}
|
onBlur={titleInputBlurHandler}
|
||||||
/>
|
/>
|
||||||
<div class="main-header__btn-wrap flex flex-v-center">
|
<div class="main-header__btn-wrap flex flex-v-center">
|
||||||
{!isAutoPreviewOn && (
|
{!isAutoPreviewOn && (
|
||||||
<button
|
<button
|
||||||
class="btn btn btn--dark flex flex-v-center hint--rounded hint--bottom-left"
|
class="btn btn btn--dark flex flex-v-center hint--rounded hint--bottom-left"
|
||||||
aria-label={i18n._(t`Run preview (Ctrl/⌘ + Shift + 5)`)}
|
aria-label={i18n._(t`Run preview (Ctrl/⌘ + Shift + 5)`)}
|
||||||
onClick={props.runBtnClickHandler}
|
onClick={runBtnClickHandler}
|
||||||
>
|
>
|
||||||
<svg>
|
<svg>
|
||||||
<use xlinkHref="#play-icon" />
|
<use xlinkHref="#play-icon" />
|
||||||
@ -39,9 +53,8 @@ export function MainHeader(props) {
|
|||||||
<Trans>Run</Trans>
|
<Trans>Run</Trans>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onClick={props.assetsBtnHandler}
|
onClick={assetsBtnHandler}
|
||||||
data-event-category="ui"
|
data-event-category="ui"
|
||||||
data-event-action="addLibraryButtonClick"
|
data-event-action="addLibraryButtonClick"
|
||||||
data-testid="addLibraryButton"
|
data-testid="addLibraryButton"
|
||||||
@ -50,8 +63,7 @@ export function MainHeader(props) {
|
|||||||
>
|
>
|
||||||
<Trans>Assets</Trans>
|
<Trans>Assets</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
|
{!isFileMode && (
|
||||||
{!props.isFileMode && (
|
|
||||||
<Button
|
<Button
|
||||||
onClick={props.addLibraryBtnHandler}
|
onClick={props.addLibraryBtnHandler}
|
||||||
data-event-category="ui"
|
data-event-category="ui"
|
||||||
@ -72,7 +84,6 @@ export function MainHeader(props) {
|
|||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn btn--dark hint--bottom-left"
|
class="btn btn--dark hint--bottom-left"
|
||||||
aria-label={i18n._(t`Share this creation publicly`)}
|
aria-label={i18n._(t`Share this creation publicly`)}
|
||||||
@ -82,9 +93,7 @@ export function MainHeader(props) {
|
|||||||
<svg
|
<svg
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
style={{
|
style={{
|
||||||
fill: props.currentItem.isPublic
|
fill: currentItem.isPublic ? 'limegreen' : 'currentColor'
|
||||||
? 'limegreen'
|
|
||||||
: 'currentColor'
|
|
||||||
}}
|
}}
|
||||||
strokeWidth="2"
|
strokeWidth="2"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
@ -92,7 +101,17 @@ export function MainHeader(props) {
|
|||||||
>
|
>
|
||||||
<path d="M18 16.08C17.24 16.08 16.56 16.38 16.04 16.85L8.91 12.7C8.96 12.47 9 12.24 9 12S8.96 11.53 8.91 11.3L15.96 7.19C16.5 7.69 17.21 8 18 8C19.66 8 21 6.66 21 5S19.66 2 18 2 15 3.34 15 5C15 5.24 15.04 5.47 15.09 5.7L8.04 9.81C7.5 9.31 6.79 9 6 9C4.34 9 3 10.34 3 12S4.34 15 6 15C6.79 15 7.5 14.69 8.04 14.19L15.16 18.34C15.11 18.55 15.08 18.77 15.08 19C15.08 20.61 16.39 21.91 18 21.91S20.92 20.61 20.92 19C20.92 17.39 19.61 16.08 18 16.08M18 4C18.55 4 19 4.45 19 5S18.55 6 18 6 17 5.55 17 5 17.45 4 18 4M6 13C5.45 13 5 12.55 5 12S5.45 11 6 11 7 11.45 7 12 6.55 13 6 13M18 20C17.45 20 17 19.55 17 19S17.45 18 18 18 19 18.45 19 19 18.55 20 18 20Z" />
|
<path d="M18 16.08C17.24 16.08 16.56 16.38 16.04 16.85L8.91 12.7C8.96 12.47 9 12.24 9 12S8.96 11.53 8.91 11.3L15.96 7.19C16.5 7.69 17.21 8 18 8C19.66 8 21 6.66 21 5S19.66 2 18 2 15 3.34 15 5C15 5.24 15.04 5.47 15.09 5.7L8.04 9.81C7.5 9.31 6.79 9 6 9C4.34 9 3 10.34 3 12S4.34 15 6 15C6.79 15 7.5 14.69 8.04 14.19L15.16 18.34C15.11 18.55 15.08 18.77 15.08 19C15.08 20.61 16.39 21.91 18 21.91S20.92 20.61 20.92 19C20.92 17.39 19.61 16.08 18 16.08M18 4C18.55 4 19 4.45 19 5S18.55 6 18 6 17 5.55 17 5 17.45 4 18 4M6 13C5.45 13 5 12.55 5 12S5.45 11 6 11 7 11.45 7 12 6.55 13 6 13M18 20C17.45 20 17 19.55 17 19S17.45 18 18 18 19 18.45 19 19 18.55 20 18 20Z" />
|
||||||
</svg>
|
</svg>
|
||||||
{props.currentItem.isPublic ? null : <Trans>Share</Trans>}
|
{currentItem.isPublic ? null : <Trans>Share</Trans>}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn--dark hint--bottom-left"
|
||||||
|
aria-label={i18n._(t`Fork this creation`)}
|
||||||
|
data-testid="headerForkButton"
|
||||||
|
onClick={onItemFork}
|
||||||
|
>
|
||||||
|
<Icon name="fork" />
|
||||||
|
<Trans>Fork</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@ -106,6 +125,8 @@ export function MainHeader(props) {
|
|||||||
</svg>
|
</svg>
|
||||||
<Trans>New</Trans>
|
<Trans>New</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{!isNotMine && (
|
||||||
<button
|
<button
|
||||||
id="saveBtn"
|
id="saveBtn"
|
||||||
class={`btn btn--dark hint--rounded hint--bottom-left ${
|
class={`btn btn--dark hint--rounded hint--bottom-left ${
|
||||||
@ -122,6 +143,7 @@ export function MainHeader(props) {
|
|||||||
</svg>
|
</svg>
|
||||||
<Trans>Save</Trans>
|
<Trans>Save</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
id="openItemsBtn"
|
id="openItemsBtn"
|
||||||
class={`btn btn--dark hint--rounded hint--bottom-left ${
|
class={`btn btn--dark hint--rounded hint--bottom-left ${
|
||||||
@ -138,7 +160,7 @@ export function MainHeader(props) {
|
|||||||
</svg>
|
</svg>
|
||||||
<Trans>Open</Trans>
|
<Trans>Open</Trans>
|
||||||
</button>
|
</button>
|
||||||
{!props.user ? (
|
{!user ? (
|
||||||
<Button
|
<Button
|
||||||
onClick={props.loginBtnHandler}
|
onClick={props.loginBtnHandler}
|
||||||
data-event-category="ui"
|
data-event-category="ui"
|
||||||
@ -160,14 +182,10 @@ export function MainHeader(props) {
|
|||||||
<img
|
<img
|
||||||
id="headerAvatarImg"
|
id="headerAvatarImg"
|
||||||
width="20"
|
width="20"
|
||||||
src={
|
src={user ? user.photoURL || DEFAULT_PROFILE_IMG : ''}
|
||||||
props.user
|
|
||||||
? props.user.photoURL || DEFAULT_PROFILE_IMG
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
class="main-header__avatar-img"
|
class="main-header__avatar-img"
|
||||||
/>
|
/>
|
||||||
{props.user?.isPro ? <ProBadge /> : null}
|
{user?.isPro ? <ProBadge /> : null}
|
||||||
</HStack>
|
</HStack>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
@ -383,9 +383,11 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
const fork = JSON.parse(JSON.stringify(sourceItem));
|
const fork = JSON.parse(JSON.stringify(sourceItem));
|
||||||
delete fork.id;
|
delete fork.id;
|
||||||
|
delete fork.createdBy;
|
||||||
fork.title = '(Forked) ' + sourceItem.title;
|
fork.title = '(Forked) ' + sourceItem.title;
|
||||||
fork.updatedOn = Date.now();
|
fork.updatedOn = Date.now();
|
||||||
this.setCurrentItem(fork).then(() => this.refreshEditor());
|
this.setCurrentItem(fork).then(() => this.refreshEditor());
|
||||||
|
route('/create');
|
||||||
alertsService.add(`"${sourceItem.title}" was forked`);
|
alertsService.add(`"${sourceItem.title}" was forked`);
|
||||||
trackEvent('fn', 'itemForked');
|
trackEvent('fn', 'itemForked');
|
||||||
}
|
}
|
||||||
@ -936,6 +938,15 @@ export default class App extends Component {
|
|||||||
var isNewItem = !this.state.currentItem.id;
|
var isNewItem = !this.state.currentItem.id;
|
||||||
this.state.currentItem.id =
|
this.state.currentItem.id =
|
||||||
this.state.currentItem.id || 'item-' + generateRandomId();
|
this.state.currentItem.id || 'item-' + generateRandomId();
|
||||||
|
if (
|
||||||
|
this.state.currentItem.createdBy &&
|
||||||
|
this.state.currentItem.createdBy !== this.state.user.uid
|
||||||
|
) {
|
||||||
|
alertsService.add(
|
||||||
|
'You cannot save this item as it was created by someone else. Fork it to save it as your own.'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
isSaving: true
|
isSaving: true
|
||||||
});
|
});
|
||||||
@ -1697,6 +1708,9 @@ export default class App extends Component {
|
|||||||
isFileMode={
|
isFileMode={
|
||||||
this.state.currentItem && this.state.currentItem.files
|
this.state.currentItem && this.state.currentItem.files
|
||||||
}
|
}
|
||||||
|
onItemFork={() => {
|
||||||
|
this.forkItem(this.state.currentItem);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{this.state.currentItem && this.state.currentItem.files ? (
|
{this.state.currentItem && this.state.currentItem.files ? (
|
||||||
<ContentWrapFiles
|
<ContentWrapFiles
|
||||||
|
Reference in New Issue
Block a user