diff --git a/src/App.tsx b/src/App.tsx
index 8a36a7d..b57bc95 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1028,12 +1028,7 @@ function App() {
const logoutFunc = useCallback(async () => {
try {
- if (hasSettingsChanged) {
- await showUnsavedChanges({
- message:
- 'Your settings have changed. If you logout you will lose your changes. Click on the save button in the header to keep your changed settings.',
- }); // TODO translate
- } else if (extState === 'authenticated') {
+ if (extState === 'authenticated') {
await showUnsavedChanges({
message: 'Are you sure you would like to logout?',
});
@@ -3014,13 +3009,16 @@ function App() {
})}
- {
returnToMain();
}}
>
- {t('core:action.continue', { postProcess: 'capitalize' })}
-
+
+ {t('core:action.continue', { postProcess: 'capitalize' })}
+
+
)}
{extState === 'transfer-success-request' && (
@@ -3221,7 +3219,7 @@ function App() {
onClick={onOkUnsavedChanges}
autoFocus
>
- {t('core:action.decline', {
+ {t('core:action.continue_logout', {
postProcess: 'capitalize',
})}
@@ -3270,6 +3268,8 @@ function App() {
lineHeight: 1.2,
maxWidth: '90%',
textAlign: 'center',
+ fontSize: '16px',
+ marginBottom: '10px',
}}
>
{messageQortalRequestExtension?.text1}
@@ -3342,11 +3342,15 @@ function App() {
)}
{messageQortalRequestExtension?.html && (
-
+ <>
+
+
+
+ >
)}
diff --git a/src/components/Apps/AppsDesktop.tsx b/src/components/Apps/AppsDesktop.tsx
index b5a5cba..80f57b9 100644
--- a/src/components/Apps/AppsDesktop.tsx
+++ b/src/components/Apps/AppsDesktop.tsx
@@ -414,8 +414,23 @@ export const AppsDesktop = ({
setDesktopViewMode('dev');
}}
>
-
-
+
+
)}
diff --git a/src/components/QortPayment.tsx b/src/components/QortPayment.tsx
index d9baa65..3b48590 100644
--- a/src/components/QortPayment.tsx
+++ b/src/components/QortPayment.tsx
@@ -158,6 +158,12 @@ export const QortPayment = ({ balance, show, onSuccess, defaultPaymentTo }) => {
value={paymentPassword}
onChange={(e) => setPaymentPassword(e.target.value)}
autoComplete="off"
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') {
+ if (isLoadingSendCoin) return;
+ sendCoinFunc();
+ }
+ }}
/>
diff --git a/src/components/ReactionPicker.tsx b/src/components/ReactionPicker.tsx
index c95adcf..911a396 100644
--- a/src/components/ReactionPicker.tsx
+++ b/src/components/ReactionPicker.tsx
@@ -27,15 +27,25 @@ export const ReactionPicker = ({ onReaction }) => {
if (showPicker) {
setShowPicker(false);
} else {
- // Get the button's position
const buttonRect = buttonRef.current.getBoundingClientRect();
const pickerWidth = 350;
+ const pickerHeight = 400; // Match Picker height prop
- // Calculate position to align the right edge of the picker with the button's right edge
- setPickerPosition({
- top: buttonRect.bottom + window.scrollY, // Position below the button
- left: buttonRect.right + window.scrollX - pickerWidth, // Align right edges
- });
+ // Initial position (below the button)
+ let top = buttonRect.bottom + window.scrollY;
+ let left = buttonRect.right + window.scrollX - pickerWidth;
+
+ // If picker would overflow bottom, show it above the button
+ const overflowBottom =
+ top + pickerHeight > window.innerHeight + window.scrollY;
+ if (overflowBottom) {
+ top = buttonRect.top + window.scrollY - pickerHeight;
+ }
+
+ // Optional: prevent overflow on the left too
+ if (left < 0) left = 0;
+
+ setPickerPosition({ top, left });
setShowPicker(true);
}
};
@@ -92,12 +102,13 @@ export const ReactionPicker = ({ onReaction }) => {
allowExpandReactions={true}
autoFocusSearch={false}
emojiStyle={EmojiStyle.NATIVE}
- height="450"
+ height={400}
onEmojiClick={handlePicker}
onReactionClick={handleReaction}
- reactionsDefaultOpen={true}
+ // reactionsDefaultOpen={true}
+ // open={true}
theme={Theme.DARK}
- width="350"
+ width={350}
/>
,
document.body
diff --git a/src/components/Theme/ThemeContext.tsx b/src/components/Theme/ThemeContext.tsx
index 72d4f3b..3ebace0 100644
--- a/src/components/Theme/ThemeContext.tsx
+++ b/src/components/Theme/ThemeContext.tsx
@@ -25,7 +25,7 @@ const ThemeContext = createContext({
toggleTheme: () => {},
userThemes: [defaultTheme],
addUserTheme: (themes) => {},
- setUserTheme: (theme) => {},
+ setUserTheme: (theme, themes) => {},
currentThemeId: 'default',
});
@@ -83,13 +83,13 @@ export const ThemeProvider = ({ children }) => {
saveSettings(themes);
};
- const setUserTheme = (theme) => {
+ const setUserTheme = (theme, themes) => {
if (theme.id === 'default') {
setCurrentThemeId('default');
- saveSettings(userThemes, themeMode, 'default');
+ saveSettings(themes || userThemes, themeMode, 'default');
} else {
setCurrentThemeId(theme.id);
- saveSettings(userThemes, themeMode, theme.id);
+ saveSettings(themes || userThemes, themeMode, theme.id);
}
};
diff --git a/src/components/Theme/ThemeManager.tsx b/src/components/Theme/ThemeManager.tsx
index eca0e9f..badcb42 100644
--- a/src/components/Theme/ThemeManager.tsx
+++ b/src/components/Theme/ThemeManager.tsx
@@ -119,7 +119,7 @@ export default function ThemeManager() {
const newTheme = { ...themeDraft, id: uid.rnd() };
const updatedThemes = [...userThemes, newTheme];
addUserTheme(updatedThemes);
- setUserTheme(newTheme);
+ setUserTheme(newTheme, updatedThemes);
}
setOpenEditor(false);
};
@@ -135,19 +135,22 @@ export default function ThemeManager() {
);
if (defaultTheme) {
- setUserTheme(defaultTheme);
+ setUserTheme(defaultTheme, updatedThemes);
} else {
// Emergency fallback
- setUserTheme({
- light: lightThemeOptions,
- dark: darkThemeOptions,
- });
+ setUserTheme(
+ {
+ light: lightThemeOptions,
+ dark: darkThemeOptions,
+ },
+ updatedThemes
+ );
}
}
};
const handleApplyTheme = (theme) => {
- setUserTheme(theme);
+ setUserTheme(theme, null);
};
const handleColorChange = (mode, fieldPath, color) => {
@@ -210,7 +213,8 @@ export default function ThemeManager() {
const newTheme = { ...importedTheme, id: uid.rnd() };
const updatedThemes = [...userThemes, newTheme];
addUserTheme(updatedThemes);
- setUserTheme(newTheme);
+
+ setUserTheme(newTheme, updatedThemes);
} catch (error) {
console.error(error);
}
diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts
index d7b040e..0a0221a 100644
--- a/src/qortalRequests/get.ts
+++ b/src/qortalRequests/get.ts
@@ -2680,7 +2680,7 @@ export const updateForeignFee = async (data) => {
const { coin, type, value } = data;
const url = `/crosschain/${coin.toLowerCase()}/update${type}`;
-
+ const valueStringified = JSON.stringify(+value);
try {
const endpoint = await createEndpoint(url);
const response = await fetch(endpoint, {
@@ -2689,7 +2689,7 @@ export const updateForeignFee = async (data) => {
Accept: '*/*',
'Content-Type': 'application/json',
},
- body: JSON.stringify({ value }),
+ body: valueStringified,
});
if (!response.ok) throw new Error('Failed to update foreign fee');
@@ -3493,6 +3493,35 @@ export const sendCoin = async (data, isFromExtension) => {
}
};
+function calculateFeeFromRate(feePerKb, sizeInBytes) {
+ return (feePerKb / 1000) * sizeInBytes;
+}
+
+const getBuyingFees = async (foreignBlockchain) => {
+ const ticker = sellerForeignFee[foreignBlockchain].ticker;
+ if (!ticker) throw new Error('invalid foreign blockchain');
+ const unlockFee = await getForeignFee({
+ coin: ticker,
+ type: 'feerequired',
+ });
+ const lockFee = await getForeignFee({
+ coin: ticker,
+ type: 'feekb',
+ });
+ return {
+ ticker: ticker,
+ lock: {
+ sats: lockFee,
+ fee: lockFee / QORT_DECIMALS,
+ },
+ unlock: {
+ sats: unlockFee,
+ fee: unlockFee / QORT_DECIMALS,
+ byteFee300: calculateFeeFromRate(+unlockFee, 300) / QORT_DECIMALS,
+ },
+ };
+};
+
export const createBuyOrder = async (data, isFromExtension) => {
const requiredFields = ['crosschainAtInfo', 'foreignBlockchain'];
const missingFields: string[] = [];
@@ -3528,6 +3557,7 @@ export const createBuyOrder = async (data, isFromExtension) => {
const crosschainAtInfo = await Promise.all(atPromises);
try {
+ const buyingFees = await getBuyingFees(foreignBlockchain);
const resPermission = await getUserPermission(
{
text1:
@@ -3541,10 +3571,45 @@ export const createBuyOrder = async (data, isFromExtension) => {
return latest + +cur?.expectedForeignAmount;
}, 0)
)}
- ${` ${crosschainAtInfo?.[0]?.foreignBlockchain}`}`,
+ ${` ${buyingFees.ticker}`}`,
highlightedText: `Is using public node: ${isGateway}`,
fee: '',
- foreignFee: `${sellerForeignFee[foreignBlockchain].value} ${sellerForeignFee[foreignBlockchain].ticker}`,
+ html: `
+
+
+
+
+
Total Unlocking Fee:
+
${(+buyingFees?.unlock?.byteFee300 * atAddresses?.length)?.toFixed(8)} ${buyingFees.ticker}
+
+ This fee is an estimate based on ${atAddresses?.length} ${atAddresses?.length > 1 ? 'orders' : 'order'} at a 300 byte cost of ${buyingFees?.unlock?.byteFee300?.toFixed(8)}
+
+
+
Total Locking Fee:
+
${+buyingFees?.unlock.fee.toFixed(8)} ${buyingFees.ticker} per kb
+
+
+
+`,
},
isFromExtension
);