Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions packages/next-common/components/comment/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import { usePost } from "next-common/context/post";
import { useCommentActions } from "next-common/sima/context/commentActions";
import { newErrorToast } from "next-common/store/reducers/toastSlice";
import { useDispatch } from "react-redux";
import Tooltip from "../tooltip";
import { useDetailType } from "next-common/context/page";
import { detailPageCategory } from "next-common/utils/consts/business/category";
import { getRealField } from "next-common/sima/actions/common";
import WatchOnlyTooltip from "next-common/components/watchOnly/tooltip";
import { useIsWatchOnly } from "next-common/context/connectedAccount";
import { WATCH_ONLY_COMMENT_TOOLTIP_TEXT } from "next-common/utils/watchOnly";

const Wrapper = styled.div`
margin-top: 48px;
Expand Down Expand Up @@ -91,6 +93,7 @@ function CommentEditor(
const { createPostComment, createCommentReply } = useCommentActions();

const shouldUseSima = useShouldUseSima(replyToComment);
const isWatchOnly = useIsWatchOnly();

const createComment = async (realAddress) => {
if (!isMounted()) {
Expand Down Expand Up @@ -191,18 +194,21 @@ function CommentEditor(
Cancel
</SecondaryButton>
)}
<Tooltip content={isEmpty ? "Cannot submit empty content" : ""}>
<WatchOnlyTooltip
content={isEmpty ? "Cannot submit empty content" : ""}
watchOnlyContent={WATCH_ONLY_COMMENT_TOOLTIP_TEXT}
>
<MaybeSplitCommentButton
isSima={shouldUseSima}
isReply={isReply}
loading={loading}
disabled={isEmpty}
disabled={isEmpty || isWatchOnly}
onClickComment={() => createComment()}
onClickCommentAsProxy={(realAddress) => {
createComment(realAddress);
}}
/>
</Tooltip>
</WatchOnlyTooltip>
</ButtonWrapper>
</Wrapper>
);
Expand Down
22 changes: 22 additions & 0 deletions packages/next-common/components/common/tx/submitButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import PrimaryButton from "next-common/lib/button/primary";
import WatchOnlyTooltip from "next-common/components/watchOnly/tooltip";
import { useIsWatchOnly } from "next-common/context/connectedAccount";

// Tx submit button. Watch-only accounts are handled here: the button is
// disabled and its tooltip becomes the watch-only hint.
export default function SubmitButton({
tooltip,
disabled = false,
children,
...props
}) {
const isWatchOnly = useIsWatchOnly();

return (
<WatchOnlyTooltip content={tooltip}>
<PrimaryButton {...props} disabled={disabled || isWatchOnly}>
{children}
</PrimaryButton>
</WatchOnlyTooltip>
);
}
29 changes: 29 additions & 0 deletions packages/next-common/components/common/tx/submitRemoveButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { SystemClose } from "@osn/icons/subsquare";
import { noop } from "lodash-es";
import { cn } from "next-common/utils";
import SubmitButton from "next-common/components/common/tx/submitButton";

// ✕ variant of SubmitButton, for buttons that submit a tx.
export default function SubmitRemoveButton({
tooltip,
disabled = false,
onClick = noop,
className,
}) {
return (
<SubmitButton
tooltip={tooltip}
disabled={disabled}
onClick={onClick}
className={cn(
"h-auto! p-1.5! rounded!",
"bg-transparent! border-neutral400!",
"text-textPrimary! disabled:text-textDisabled!",
"cursor-pointer disabled:cursor-not-allowed!",
className,
)}
>
<SystemClose width={16} height={16} />
</SubmitButton>
);
}
36 changes: 22 additions & 14 deletions packages/next-common/components/common/tx/txSubmissionButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import PrimaryButton from "next-common/lib/button/primary";
import LoadingButton from "next-common/lib/button/loading";
import useTxSubmission from "./useTxSubmission";
import { usePopupOnClose } from "next-common/context/popup";
import WatchOnlyTooltip from "next-common/components/watchOnly/tooltip";
import { useIsWatchOnly } from "next-common/context/connectedAccount";

export default function TxSubmissionButton({
api,
Expand All @@ -21,6 +23,7 @@ export default function TxSubmissionButton({
autoClose = true,
}) {
const onClose = usePopupOnClose();
const isWatchOnly = useIsWatchOnly();
const { isSubmitting, isWrapping, doSubmit } = useTxSubmission({
api,
getTxFunc,
Expand All @@ -44,13 +47,15 @@ export default function TxSubmissionButton({
{isLoading && loadingText ? (
<LoadingButton>{loadingText}</LoadingButton>
) : (
<PrimaryButton
loading={isLoading}
onClick={doSubmit}
disabled={disabled}
>
{title}
</PrimaryButton>
<WatchOnlyTooltip>
<PrimaryButton
loading={isLoading}
onClick={doSubmit}
disabled={disabled || isWatchOnly}
>
{title}
</PrimaryButton>
</WatchOnlyTooltip>
)}
</div>
);
Expand All @@ -68,6 +73,7 @@ export function useTxSubmissionButton({
onTxError = noop,
onTxStart = noop,
}) {
const isWatchOnly = useIsWatchOnly();
const { isSubmitting, isWrapping, doSubmit } = useTxSubmission({
getTxFunc,
onFinalized,
Expand All @@ -86,13 +92,15 @@ export function useTxSubmissionButton({
{isSubmitting && loadingText ? (
<LoadingButton>{loadingText}</LoadingButton>
) : (
<PrimaryButton
loading={isSubmitting || isWrapping}
onClick={doSubmit}
disabled={disabled}
>
{title}
</PrimaryButton>
<WatchOnlyTooltip>
<PrimaryButton
loading={isSubmitting || isWrapping}
onClick={doSubmit}
disabled={disabled || isWatchOnly}
>
{title}
</PrimaryButton>
</WatchOnlyTooltip>
)}
</div>
),
Expand Down
9 changes: 9 additions & 0 deletions packages/next-common/components/common/tx/useTxSubmission.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { wrapTransaction } from "next-common/utils/sendTransaction";
import { useContextApi } from "next-common/context/api";
import { useSendTransaction } from "next-common/hooks/useSendTransaction";
import { useMaybeMultisigCallback } from "./useMaybeMultisigCallback";
import { useIsWatchOnly } from "next-common/context/connectedAccount";
import { WATCH_ONLY_TOOLTIP_TEXT } from "next-common/utils/watchOnly";

export default function useTxSubmission({
api,
Expand All @@ -22,6 +24,7 @@ export default function useTxSubmission({
const defaultApi = useContextApi();
const apiToUse = api || defaultApi;
const signerAccount = useSignerAccount();
const isWatchOnly = useIsWatchOnly();
const { sendTxFunc, isSubmitting } = useSendTransaction();
const {
onInBlock: maybeMultisigOnInBlock,
Expand Down Expand Up @@ -51,6 +54,11 @@ export default function useTxSubmission({

const doSubmit = useCallback(
async (...args) => {
if (isWatchOnly) {
dispatch(newErrorToast(WATCH_ONLY_TOOLTIP_TEXT));
return;
}

if (!apiToUse) {
dispatch(newErrorToast("Chain RPC is not connected yet"));
return;
Expand Down Expand Up @@ -87,6 +95,7 @@ export default function useTxSubmission({
[
apiToUse,
dispatch,
isWatchOnly,
signerAccount,
getTx,
sendTxFunc,
Expand Down
18 changes: 15 additions & 3 deletions packages/next-common/components/fellowship/applications/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { useRouter } from "next/router";
import { useExtensionAccounts } from "next-common/components/popupWithSigner/context";
import AddressCombo from "next-common/components/addressCombo";
import SignerPopupWrapper from "next-common/components/popupWithSigner/signerPopupWrapper";
import WatchOnlyTooltip from "next-common/components/watchOnly/tooltip";
import { useIsWatchOnly } from "next-common/context/connectedAccount";
import { WATCH_ONLY_CREATE_APPLICATION_TOOLTIP_TEXT } from "next-common/utils/watchOnly";

function PageTitle() {
return (
Expand Down Expand Up @@ -109,6 +112,7 @@ function CreateFellowshipApplicationImpl() {
const [contentType, setContentType] = useState("markdown");
const [loading, setLoading] = useState(false);
const { ensureLogin } = useEnsureLogin();
const isWatchOnly = useIsWatchOnly();

const createApplication = async () => {
setLoading(true);
Expand Down Expand Up @@ -154,9 +158,17 @@ function CreateFellowshipApplicationImpl() {
setContentType={setContentType}
/>
<div className="flex justify-end">
<PrimaryButton loading={loading} onClick={createApplication}>
Create
</PrimaryButton>
<WatchOnlyTooltip
watchOnlyContent={WATCH_ONLY_CREATE_APPLICATION_TOOLTIP_TEXT}
>
<PrimaryButton
loading={loading}
onClick={createApplication}
disabled={isWatchOnly}
>
Create
</PrimaryButton>
</WatchOnlyTooltip>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback } from "react";
import PrimaryButton from "next-common/lib/button/primary";
import SubmitButton from "next-common/components/common/tx/submitButton";
import { useCoreFellowshipPallet } from "next-common/context/collectives/collectives";
import Tooltip from "next-common/components/tooltip";
import { useFellowshipCanInductMember } from "next-common/hooks/fellowship/useFellowshipCanInductMember";
Expand Down Expand Up @@ -48,13 +49,13 @@ function InductButton({ address }) {
<Tooltip
content={!canInductMember && "Only available to members with rank >= 3"}
>
<PrimaryButton
<SubmitButton
size="small"
disabled={!canInductMember}
onClick={doSubmit}
>
Induct
</PrimaryButton>
</SubmitButton>
</Tooltip>
</>
);
Expand Down
31 changes: 31 additions & 0 deletions packages/next-common/components/header/connectedAccountDisplay.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { SystemEye } from "@osn/icons/subsquare";
import { cn } from "next-common/utils";
import { AddressUser } from "next-common/components/user";
import Tooltip from "next-common/components/tooltip";
import { useIsWatchOnly } from "next-common/context/connectedAccount";

// Connected account shown in the header. A watch-only account gets an eye badge
// on its avatar: it is absolutely positioned, so the display size is unchanged.
export default function ConnectedAccountDisplay({ address, className }) {
const isWatchOnly = useIsWatchOnly();
const account = <AddressUser add={address} noEvent />;

if (!isWatchOnly) {
return account;
}

return (
<Tooltip content="Watch-only account">
<div className={cn("relative flex items-center", className)}>
{account}
<SystemEye
className={cn(
"absolute left-1.5 bottom-0",
"w-3.5 h-3.5 p-px",
"rounded-full bg-neutral100 text-textSecondary",
)}
/>
</div>
</Tooltip>
);
}
11 changes: 8 additions & 3 deletions packages/next-common/components/header/drawer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { walletConnect } from "next-common/utils/consts/connect/index.js";
import { useAccountMenu } from "./useAccountMenu";
import Divider from "next-common/components/styled/layout/divider";
import SwitchAccount from "next-common/components/switchAccount";
import AddressUser from "next-common/components/user/addressUser";
import ConnectedAccountDisplay from "./connectedAccountDisplay.jsx";
import { useIsWatchOnly } from "next-common/context/connectedAccount";
import SearchInputWithPopup from "./searchInputWithPopup";
import { useWalletConnect } from "next-common/context/walletconnect";
import Loading from "next-common/components/loading";
Expand Down Expand Up @@ -66,14 +67,18 @@ function ProfileMenuItem({ onClick }) {
}

function ConnectedAccount({ user }) {
const isWatchOnly = useIsWatchOnly();

if (!user?.address) {
return null;
}

return (
<div className="flex items-center justify-between rounded-lg bg-neutral200 border-none h-10 mb-2 pl-2 pr-4">
<AddressUser add={user?.address} key={user?.address} />
<span className="text12Medium text-textTertiary">Connected</span>
<ConnectedAccountDisplay address={user?.address} />
<span className="text12Medium text-textTertiary">
{isWatchOnly ? "Watch-only" : "Connected"}
</span>
</div>
);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/next-common/components/header/headerAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { useLoginPopup } from "next-common/hooks/useLoginPopup.js";
import SecondaryButton from "next-common/lib/button/secondary";
import { SystemProfile } from "@osn/icons/subsquare";
import { useConnectedAccountContext } from "next-common/context/connectedAccount/index.js";
import { AddressUser, SystemUser } from "../user";
import { SystemUser } from "../user";
import ConnectedAccountDisplay from "./connectedAccountDisplay.jsx";
import { useAccountMenu } from "./useAccountMenu.js";
import { walletConnect } from "next-common/utils/consts/connect/index.js";
import { useWalletConnect } from "next-common/context/walletconnect/index.jsx";
Expand Down Expand Up @@ -121,7 +122,7 @@ export default function HeaderAccount() {
} else {
connectBtn = (
<SecondaryButton onClick={() => setShow(!show)}>
<AddressUser add={user?.address} noEvent />
<ConnectedAccountDisplay address={user?.address} />
</SecondaryButton>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import useAddressComboField from "next-common/components/preImages/createPreimag
import AdvanceSettings from "next-common/components/summary/newProposalQuickStart/common/advanceSettings";
import { useUser } from "next-common/context/user";
import { useSendTransaction } from "next-common/hooks/useSendTransaction";
import PrimaryButton from "next-common/lib/button/primary";
import SubmitButton from "next-common/components/common/tx/submitButton";
import {
newErrorToast,
newSuccessToast,
Expand Down Expand Up @@ -153,9 +153,9 @@ function PopupContent() {
/>
</AdvanceSettings>
<div className="flex justify-end">
<PrimaryButton loading={isSubmitting} onClick={doSubmit}>
<SubmitButton loading={isSubmitting} onClick={doSubmit}>
Submit
</PrimaryButton>
</SubmitButton>
</div>
</>
);
Expand Down
3 changes: 3 additions & 0 deletions packages/next-common/components/login/web3/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import LoginWeb3Substrate from "./substrate";
import { useUnmount } from "react-use";
import LoginWeb3WalletConnect from "./walletconnect";
import LoginWeb3PolkadotVault from "./polkadotVault";
import LoginWeb3WatchOnly from "./watchOnly";
import { useChainSettings } from "next-common/context/chain";

export default function LoginWeb3({ setIsWeb3 = noop }) {
Expand All @@ -14,6 +15,7 @@ export default function LoginWeb3({ setIsWeb3 = noop }) {
isEVMView,
isWalletConnectView,
isPolkadotVaultView,
isWatchOnlyView,
resetView,
} = useWeb3WalletView();

Expand All @@ -27,6 +29,7 @@ export default function LoginWeb3({ setIsWeb3 = noop }) {

{isWalletConnectView && <LoginWeb3WalletConnect />}
{isPolkadotVaultView && <LoginWeb3PolkadotVault />}
{isWatchOnlyView && <LoginWeb3WatchOnly />}

{chainSettings?.allowWeb2Login && (
<div className="text-center text14Medium text-textSecondary">
Expand Down
Loading
Loading