Files
2026-02-12 19:07:08 -08:00

220 lines
11 KiB
PHP
Raw Permalink 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.
<?php
declare(strict_types=1);
style('qortal_integration', 'qapps');
script('qortal_integration', 'qapps');
$qapps = $_['qappsList'] ?? [];
?>
<div
id="qortal-qapps-root"
class="section"
data-qapps="<?php p(json_encode($qapps, JSON_UNESCAPED_SLASHES)); ?>"
data-qapps-enabled="<?php p(!empty($_['qappsEnabled']) ? '1' : '0'); ?>"
data-qapps-browser-enabled="<?php p(!empty($_['qappsFullBrowserEnabled']) ? '1' : '0'); ?>"
data-qapps-browser-address="<?php p((string)($_['qappsFullBrowserAddress'] ?? '')); ?>"
data-qapps-debug-enabled="<?php p(!empty($_['qappsDebugEnabled']) ? '1' : '0'); ?>"
data-qortal-node-url="<?php p((string)($_['qortalNodeUrl'] ?? '')); ?>"
data-qortal-gateway-url="<?php p((string)($_['qortalGatewayUrl'] ?? '')); ?>"
data-gateway-proxy-url="<?php p((string)($_['gatewayProxyUrl'] ?? '')); ?>"
data-qapps-request-url="<?php p((string)($_['qappsRequestUrl'] ?? '')); ?>"
data-qapps-approve-url="<?php p((string)($_['qappsApproveUrl'] ?? '')); ?>"
data-qapps-permissions-url="<?php p((string)($_['qappsPermissionsUrl'] ?? '')); ?>"
data-qapps-unlock-url="<?php p((string)($_['qappsUnlockUrl'] ?? '')); ?>"
data-qapps-unlock-status-url="<?php p((string)($_['qappsUnlockStatusUrl'] ?? '')); ?>"
data-qapps-default-approval-mode="<?php p((string)($_['qappsDefaultApprovalMode'] ?? 'once')); ?>"
data-qapps-default-approval-temp-minutes="<?php p((string)($_['qappsDefaultApprovalTempMinutes'] ?? 10)); ?>"
data-qapps-default-approval-unlock-10-min="<?php p(!empty($_['qappsDefaultApprovalUnlock10Min']) ? '1' : '0'); ?>"
data-qapps-default-unlock-session-20-min="<?php p(!empty($_['qappsDefaultUnlockSession20Min']) ? '1' : '0'); ?>"
data-nextcloud-public-url="<?php p((string)($_['nextcloudPublicUrl'] ?? '')); ?>"
data-user-mappings-url="<?php p((string)($_['userMappingsUrl'] ?? '')); ?>"
data-settings-path="<?php p((string)($_['settingsPath'] ?? '')); ?>"
>
<div class="qortal-page-header">
<div>
<h2><?php p((string)($_['title'] ?? 'Q-Apps')); ?></h2>
<p class="qortal-help">Launch approved Q-Apps from inside Nextcloud.</p>
</div>
</div>
<div id="qortal-qapps-empty" class="qortal-card">
<p class="qortal-note">Q-Apps access is not enabled yet. Ask an admin to enable it.</p>
</div>
<div id="qortal-qapps-browser" class="qortal-card">
<h3>Full Qortal Browser</h3>
<p class="qortal-note">
Open the full Qortal browser for unrestricted Q-App access.
</p>
<p class="qortal-note">
Address: <code id="qortal-qapps-browser-address"></code>
</p>
<button id="qortal-qapps-open-browser" class="button button-primary">Open Full Browser</button>
</div>
<div id="qortal-qapps-warning" class="qortal-card qortal-hidden">
<h3>View-only mode</h3>
<p class="qortal-note">
No Qortal account is linked to your Nextcloud user yet. You can browse Q-Apps, but authentication-required
actions will not work until you create or attach a Qortal account.
</p>
<p class="qortal-note">
<a id="qortal-qapps-settings-link" class="button" href="#">Open Qortal Settings</a>
</p>
</div>
<div id="qortal-qapps-name-required" class="qortal-modal qortal-hidden">
<div class="qortal-modal__backdrop"></div>
<div class="qortal-modal__card qortal-modal__card--danger">
<h3>Registered Name Needed</h3>
<p class="qortal-note">
You do not have a registered Qortal name.
</p>
<p class="qortal-note">
In order to publish data or messages within Q-Apps to Qortal's distributed data network, you must register a name first.
</p>
<div class="qortal-approval-actions qortal-name-required-actions">
<a id="qortal-qapps-name-required-dashboard" class="button button-primary" href="#">Open Dashboard</a>
<button id="qortal-qapps-name-required-continue" class="button" type="button">Continue Anyway</button>
<button id="qortal-qapps-name-required-cancel" class="button" type="button">Cancel</button>
</div>
</div>
</div>
<div id="qortal-qapps-list" class="qortal-card">
<h3>Available Q-Apps</h3>
<p class="qortal-note">Launch approved Q-Apps from this list, or use Full Browser mode for unrestricted navigation.</p>
<div class="qortal-table-wrap">
<table class="qortal-table">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Description</th>
<th>Action</th>
</tr>
</thead>
<tbody id="qortal-qapps-body">
<tr>
<td colspan="4">Loading…</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="qortal-qapps-viewer" class="qortal-card qortal-hidden">
<div class="qortal-viewer-toolbar">
<div class="qortal-viewer-nav-actions">
<button id="qortal-qapps-back" class="button">Back</button>
<button id="qortal-qapps-reload" class="button">Reload</button>
</div>
<div class="qortal-viewer-address">
<code id="qortal-qapps-viewer-address" class="qortal-viewer-address-text"></code>
<div class="qortal-viewer-address-input">
<input id="qortal-qapps-viewer-address-input" class="qortal-input" type="text" placeholder="qortal://APP/Q-Tube">
<button id="qortal-qapps-viewer-address-go" class="button">Go</button>
</div>
<span id="qortal-qapps-loading-progress" class="qortal-qdn-progress qortal-hidden" aria-live="polite"></span>
</div>
<div class="qortal-viewer-actions">
<button id="qortal-qapps-menu" class="button qortal-mobile-only" type="button" aria-controls="qortal-qapps-root" aria-expanded="false">Menu</button>
<button id="qortal-qapps-open-external" class="button" type="button">Copy link</button>
<button id="qortal-qapps-close" class="button" type="button" aria-label="Close Q-App viewer">×</button>
</div>
</div>
<div id="qortal-qapps-frame-wrap" class="qortal-viewer-frame-wrap">
<div id="qortal-qapps-loading-overlay" class="qortal-loading-overlay qortal-hidden" aria-live="polite" aria-atomic="true">
<div class="qortal-loading-card">
<div class="qortal-loading-title">Loading from QDN</div>
<div id="qortal-qapps-loading-status" class="qortal-loading-status">Preparing resource...</div>
<div class="qortal-loading-progress-track">
<div id="qortal-qapps-loading-progress-bar" class="qortal-loading-progress-bar"></div>
</div>
<div id="qortal-qapps-loading-meta" class="qortal-loading-meta"></div>
</div>
</div>
<iframe id="qortal-qapps-frame" title="Q-App Viewer" loading="lazy" scrolling="yes"></iframe>
</div>
</div>
<div id="qortal-qapps-debug" class="qortal-card qortal-hidden">
<div class="qortal-debug-header">
<h3>Q-Apps Debug</h3>
<div class="qortal-debug-actions">
<button id="qortal-qapps-debug-minimize" class="button">Minimize</button>
<button id="qortal-qapps-debug-float" class="button">Float Panel</button>
<button id="qortal-qapps-debug-copy" class="button">Copy Logs</button>
<button id="qortal-qapps-debug-clear" class="button">Clear</button>
</div>
</div>
<pre id="qortal-qapps-debug-body" class="qortal-status qortal-compact-status">Debug panel enabled.</pre>
</div>
<div id="qortal-qapps-approval" class="qortal-modal qortal-hidden">
<div class="qortal-modal__backdrop"></div>
<div class="qortal-modal__card">
<h3>Authorize Qortal Request</h3>
<p class="qortal-note">Choose how this Qortal request should be handled. Broker/API session auth is automatic while you are logged into Nextcloud.</p>
<div class="qortal-approval-details">
<div><span class="qortal-label">App</span> <span id="qortal-approval-app" class="qortal-value">—</span></div>
<div><span class="qortal-label">Action</span> <span id="qortal-approval-action" class="qortal-value">—</span></div>
</div>
<div class="qortal-approval-options">
<label><input type="radio" name="qortal-approval-mode" value="once" checked> Allow only this request</label>
<label><input type="radio" name="qortal-approval-mode" value="type_minutes"> Allow this request type for X minutes</label>
<label><input type="radio" name="qortal-approval-mode" value="type_always"> Always allow this request type</label>
<label><input type="radio" name="qortal-approval-mode" value="app_always"> Always allow all request types for this Q-App</label>
</div>
<div class="qortal-unlock-field">
<label class="qortal-label" for="qortal-approval-temp-minutes">X Minutes (for temporary type approval)</label>
<input id="qortal-approval-temp-minutes" class="qortal-input" type="number" min="1" max="1440" step="1" value="10">
</div>
<p id="qortal-approval-policy-status" class="qortal-note qortal-approval-help"></p>
<p class="qortal-note qortal-approval-help">Persistent approval rules are stored in External Auth permissions. Temporary type approval is kept in this browser tab for the selected duration.</p>
<p id="qortal-approval-wallet-status" class="qortal-note qortal-approval-wallet-status qortal-wallet-status-unknown">Wallet lock: unknown (password may be required)</p>
<div id="qortal-approval-unlock-fields" class="qortal-approval-unlock qortal-hidden">
<label class="qortal-label" for="qortal-approval-password">Wallet password</label>
<input id="qortal-approval-password" class="qortal-input" type="password" placeholder="Needed only if wallet is currently locked" autocomplete="current-password">
<label class="qortal-unlock-option">
<input id="qortal-approval-ttl" type="checkbox">
Also unlock wallet for 10 min (password required)
</label>
<p class="qortal-note qortal-approval-help">Wallet password is only needed when the wallet is locked.</p>
</div>
<div class="qortal-approval-actions">
<button id="qortal-approval-confirm" class="button button-primary">Approve</button>
<button id="qortal-approval-cancel" class="button">Cancel</button>
</div>
<p id="qortal-approval-error" class="qortal-note qortal-approval-error qortal-hidden"></p>
</div>
</div>
<div id="qortal-qapps-unlock" class="qortal-modal qortal-hidden">
<div class="qortal-modal__backdrop"></div>
<div class="qortal-modal__card">
<h3>Unlock Qortal Wallet</h3>
<p class="qortal-note">Your wallet is locked. Enter your wallet password to continue.</p>
<div class="qortal-approval-details">
<div><span class="qortal-label">App</span> <span id="qortal-unlock-app" class="qortal-value">—</span></div>
<div><span class="qortal-label">Action</span> <span id="qortal-unlock-action" class="qortal-value">—</span></div>
</div>
<div class="qortal-unlock-field">
<label class="qortal-label" for="qortal-unlock-password">Wallet password</label>
<input id="qortal-unlock-password" class="qortal-input" type="password" placeholder="Enter wallet password" autocomplete="current-password">
</div>
<label class="qortal-unlock-option">
<input id="qortal-unlock-session" type="checkbox">
Keep wallet unlocked for 20 minutes
</label>
<div class="qortal-approval-actions">
<button id="qortal-unlock-confirm" class="button button-primary">Unlock</button>
<button id="qortal-unlock-cancel" class="button">Cancel</button>
</div>
<p id="qortal-unlock-error" class="qortal-note qortal-approval-error qortal-hidden"></p>
</div>
</div>
</div>