Skip to content
Draft
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
45 changes: 32 additions & 13 deletions lib/Controller/OCSController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCA\Richdocuments\DirectEditing\OfficeDirectEditor;
use OCA\Richdocuments\Exceptions\ExpiredTokenException;
use OCA\Richdocuments\Exceptions\UnknownTokenException;
use OCA\Richdocuments\Listener\RegisterDirectEditorListener;
use OCA\Richdocuments\Service\FederationService;
use OCA\Richdocuments\TemplateManager;
use OCA\Richdocuments\TokenManager;
Expand Down Expand Up @@ -86,28 +87,46 @@ public function createDirect($fileId) {
throw new OCSBadRequestException('Cannot view folder');
}

// getRelativePath() can return null for nodes outside the user
// folder; Manager::open() requires a string, so fall back to the
// filename which is enough for the manager to resolve by fileId.
$path = $userFolder->getRelativePath($node->getPath()) ?? $node->getName();

// Register directly so the legacy endpoint keeps working for
// older mobile clients where RegisterDirectEditorListener gates
// out the editor from OCP\DirectEditing discovery.
$this->directEditingManager->registerDirectEditor($this->officeDirectEditor);
/** @psalm-suppress UndefinedInterfaceMethod IManager does not expose open() but the concrete Manager does, same pattern as files-app DirectEditingController */
$token = $this->directEditingManager->open($path, Application::APPNAME, $node->getId());
if ($this->isAndroidV34OrAbove()) {
// Android v34+ uses the server's OCP\DirectEditing API natively
// (via /ocs/v2.php/apps/files/directEditing/open) but may fall back
// to this legacy endpoint — serve the server-managed URL so the
// TextEditorWebView flow works end-to-end.
$path = $userFolder->getRelativePath($node->getPath()) ?? $node->getName();
$this->directEditingManager->registerDirectEditor($this->officeDirectEditor);
/** @psalm-suppress UndefinedInterfaceMethod IManager does not expose open() but the concrete Manager does, same pattern as files-app DirectEditingController */
$token = $this->directEditingManager->open($path, Application::APPNAME, $node->getId());
return new DataResponse([
'url' => $this->urlGenerator->linkToRouteAbsolute('files.DirectEditingView.edit', [
'token' => $token,
]),
]);
}

// iOS (all versions) and Android < 34: use the legacy richdocuments direct
// token. These clients open the URL in RichDocumentsEditorWebView which
// injects window.RichDocumentsMobileInterface. The server's generic
// TextEditorWebView (used for Android v34+) injects a different interface
// and these older clients cannot drive it.
$direct = $this->directMapper->newDirect($this->userId, $node->getId());
return new DataResponse([
'url' => $this->urlGenerator->linkToRouteAbsolute('files.DirectEditingView.edit', [
'token' => $token,
'url' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.directView.show', [
'token' => $direct->getToken(),
]),
]);
} catch (NotFoundException) {
throw new OCSNotFoundException();
}
}

private function isAndroidV34OrAbove(): bool {
$userAgent = $this->request->getHeader('User-Agent');
if (preg_match(IRequest::USER_AGENT_CLIENT_ANDROID, $userAgent, $matches) !== 1) {
return false;
}
return (int)explode('.', $matches[1] ?? '0')[0] >= RegisterDirectEditorListener::MIN_MOBILE_CLIENT_VERSION;
}

/**
* Generate a direct editing link for a file in a public share to open with the current user
*
Expand Down
2 changes: 1 addition & 1 deletion lib/Listener/RegisterDirectEditorListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ final class RegisterDirectEditorListener implements IEventListener {
* legacy /apps/richdocuments/api/v1/document endpoint and should not
* see the editor in OCP\DirectEditing discovery responses.
*/
private const MIN_MOBILE_CLIENT_VERSION = 34;
public const MIN_MOBILE_CLIENT_VERSION = 34;

public function __construct(
private OfficeDirectEditor $editor,
Expand Down
13 changes: 12 additions & 1 deletion src/helpers/mobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import Config from './../services/config.tsx'
const isDirectEditing = () => Config.get('direct')

const isMobileInterfaceAvailable = () => window.RichDocumentsMobileInterface
|| window.DirectEditingMobileInterface
|| (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.RichDocumentsMobileInterface)

const isMobileInterfaceOnIos = () => window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.RichDocumentsMobileInterface

const isMobileInterfaceOnAndroid = () => window.RichDocumentsMobileInterface
|| window.DirectEditingMobileInterface

const callMobileMessage = (messageName, attributes) => {
console.debug('callMobileMessage', messageName, attributes)
Expand All @@ -29,7 +31,7 @@ const callMobileMessage = (messageName, attributes) => {
} catch (e) {
attributesString = null
}
// Forward to mobile handler
// Forward to RichDocuments-specific mobile handler (legacy richdocuments WebView)
if (window.RichDocumentsMobileInterface && typeof window.RichDocumentsMobileInterface[messageName] === 'function') {
if (attributesString === null || typeof attributesString === 'undefined') {
window.RichDocumentsMobileInterface[messageName]()
Expand All @@ -38,6 +40,15 @@ const callMobileMessage = (messageName, attributes) => {
}
}

// Forward to generic direct editing mobile handler (server's OCP\DirectEditing WebView, Android v34+)
if (window.DirectEditingMobileInterface && typeof window.DirectEditingMobileInterface[messageName] === 'function') {
if (attributesString === null || typeof attributesString === 'undefined') {
window.DirectEditingMobileInterface[messageName]()
} else {
window.DirectEditingMobileInterface[messageName](attributesString)
}
}

// iOS webkit fallback
if (window.webkit
&& window.webkit.messageHandlers
Expand Down
Loading