diff --git a/android/app/src/main/java/org/lichess/mobileapp/LiShare.java b/android/app/src/main/java/org/lichess/mobileapp/LiShare.java new file mode 100644 index 0000000000..a70044d44c --- /dev/null +++ b/android/app/src/main/java/org/lichess/mobileapp/LiShare.java @@ -0,0 +1,45 @@ +package org.lichess.mobileapp; + +import android.content.Intent; + +import com.getcapacitor.NativePlugin; +import com.getcapacitor.Plugin; +import com.getcapacitor.PluginCall; +import com.getcapacitor.PluginMethod; + +@NativePlugin() +public class LiShare extends Plugin { + + @PluginMethod() + public void share(PluginCall call) { + String title = call.getString("title", ""); + String text = call.getString("text"); + String url = call.getString("url"); + + if (text == null && url == null) { + call.error("Must provide a URL or Message"); + return; + } + + // If they supplied both fields, concat em + if (text != null && url != null) { + text = text + " " + url; + } else if(url != null) { + text = url; + } + + Intent intent = new Intent(Intent.ACTION_SEND); + intent.putExtra(Intent.EXTRA_TEXT, text); + intent.setTypeAndNormalize("text/plain"); + + if (title != null) { + intent.putExtra(Intent.EXTRA_SUBJECT, title); + } + + Intent chooser = Intent.createChooser(intent, null); + chooser.addCategory(Intent.CATEGORY_DEFAULT); + + getActivity().startActivity(chooser); + call.success(); + } +} diff --git a/android/app/src/main/java/org/lichess/mobileapp/MainActivity.java b/android/app/src/main/java/org/lichess/mobileapp/MainActivity.java index b9b4462734..d24c800859 100644 --- a/android/app/src/main/java/org/lichess/mobileapp/MainActivity.java +++ b/android/app/src/main/java/org/lichess/mobileapp/MainActivity.java @@ -37,6 +37,7 @@ public void onCreate(Bundle savedInstanceState) { this.init(savedInstanceState, new ArrayList>() {{ // Additional plugins you've installed go here add(LiToast.class); + add(LiShare.class); add(SoundEffect.class); }}); diff --git a/src/ui/ai/AiRound.ts b/src/ui/ai/AiRound.ts index 54f6080b72..b4a42a85d8 100644 --- a/src/ui/ai/AiRound.ts +++ b/src/ui/ai/AiRound.ts @@ -174,7 +174,7 @@ export default class AiRound implements AiRoundInterface, PromotingInterface { public sharePGN = () => { this.replay.pgn(this.white(), this.black()) .then((data: chess.PgnDumpResponse) => - Plugins.Share.share({ text: data.pgn }) + Plugins.LiShare.share({ text: data.pgn }) ) } diff --git a/src/ui/analyse/menu.ts b/src/ui/analyse/menu.ts index 6a08cd8890..ee60a0a676 100644 --- a/src/ui/analyse/menu.ts +++ b/src/ui/analyse/menu.ts @@ -109,7 +109,7 @@ function renderShareMenu(ctrl: AnalyseCtrl) { isOnlineAnalyseData(ctrl.data) ? h('button', { oncreate: helper.ontap(() => { ctrl.menu.close() - Plugins.Share.share({ url: gameApi.publicAnalyseUrl(ctrl.data) }) + Plugins.LiShare.share({ url: gameApi.publicAnalyseUrl(ctrl.data) }) }) }, [i18n('shareGameURL')]) : null, ctrl.source === 'offline' ? h('button', { @@ -130,7 +130,7 @@ function renderShareMenu(ctrl: AnalyseCtrl) { ctrl.isOfflineOrNotPlayable() ? h('button', { oncreate: helper.ontap(() => { ctrl.menu.close() - Plugins.Share.share({ text: ctrl.node.fen }) + Plugins.LiShare.share({ text: ctrl.node.fen }) }), }, 'Share current FEN') : null, ])) @@ -146,7 +146,7 @@ function onlinePGNExport(ctrl: AnalyseCtrl, raw: boolean) { ctrl.menu.s.computingPGNAnnotated = false ctrl.menu.close() redraw() - Plugins.Share.share({ text: pgn }) + Plugins.LiShare.share({ text: pgn }) }) .catch(e => { ctrl.menu.s.computingPGN = false @@ -178,7 +178,7 @@ function offlinePgnExport(ctrl: AnalyseCtrl) { ctrl.menu.s.computingPGN = false ctrl.menu.close() redraw() - Plugins.Share.share({ text: res.pgn }) + Plugins.LiShare.share({ text: res.pgn }) }) .catch(e => { ctrl.menu.s.computingPGN = false diff --git a/src/ui/analyse/study/actionMenu.ts b/src/ui/analyse/study/actionMenu.ts index a8caa2966f..f2a88233b6 100644 --- a/src/ui/analyse/study/actionMenu.ts +++ b/src/ui/analyse/study/actionMenu.ts @@ -116,7 +116,7 @@ function renderShareMenu(ctrl: AnalyseCtrl) { ctrl.study!.actionMenu.s.loadingChapterPGN = false ctrl.study!.actionMenu.s.loadingStudyPGN = false redraw() - Plugins.Share.share({ text: pgn }) + Plugins.LiShare.share({ text: pgn }) } function onPgnError(e: ErrorResponse) { @@ -130,13 +130,13 @@ function renderShareMenu(ctrl: AnalyseCtrl) { h('button', { oncreate: helper.ontap(() => { const url = baseUrl + `study/${ctrl.study!.data.id}` - Plugins.Share.share({ url }) + Plugins.LiShare.share({ url }) }) }, [i18n('Study URL')]), h('button', { oncreate: helper.ontap(() => { const url = baseUrl + `study/${ctrl.study!.data.id}/${ctrl.study!.data.chapter.id}` - Plugins.Share.share({ url }) + Plugins.LiShare.share({ url }) }) }, [i18n('Current chapter URL')]), h('button', { diff --git a/src/ui/challenge/challengeView.tsx b/src/ui/challenge/challengeView.tsx index b23cd30160..db045f8604 100644 --- a/src/ui/challenge/challengeView.tsx +++ b/src/ui/challenge/challengeView.tsx @@ -97,7 +97,7 @@ export function awaitInvitePopup(ctrl: ChallengeState, challenge: Challenge) { h('div.go_or_cancel.clearfix', [ h('button.binary_choice[data-icon=E].withIcon', { oncreate: helper.ontap(function() { - Plugins.Share.share({ url: publicUrl(challenge) }) + Plugins.LiShare.share({ url: publicUrl(challenge) }) }) }, i18n('shareGameURL')), h('button.binary_choice[data-icon=L].withIcon', { diff --git a/src/ui/editor/editorView.ts b/src/ui/editor/editorView.ts index 082ceffb39..e9efc2a4a4 100644 --- a/src/ui/editor/editorView.ts +++ b/src/ui/editor/editorView.ts @@ -89,7 +89,7 @@ function renderActionsBar(ctrl: EditorCtrl) { }), h('button.action_bar_button.fa.fa-share-alt', { oncreate: helper.ontap( - () => Plugins.Share.share({ text: ctrl.computeFen() }), + () => Plugins.LiShare.share({ text: ctrl.computeFen() }), () => Plugins.LiToast.show({ text: 'Share FEN', duration: 'short', position: 'bottom' }) ) }) diff --git a/src/ui/otb/OtbRound.ts b/src/ui/otb/OtbRound.ts index 986aae95ab..a17da9db0a 100644 --- a/src/ui/otb/OtbRound.ts +++ b/src/ui/otb/OtbRound.ts @@ -204,7 +204,7 @@ export default class OtbRound implements OtbRoundInterface, PromotingInterface { public sharePGN = () => { this.replay.pgn('White', 'Black') .then((data: chess.PgnDumpResponse) => - Plugins.Share.share({ text: data.pgn }) + Plugins.LiShare.share({ text: data.pgn }) ) } diff --git a/src/ui/shared/round/view/button.tsx b/src/ui/shared/round/view/button.tsx index 3f32cb6cb7..934c539ae1 100644 --- a/src/ui/shared/round/view/button.tsx +++ b/src/ui/shared/round/view/button.tsx @@ -32,7 +32,7 @@ export default { shareLink(ctrl: OnlineRound) { return h('button', { oncreate: helper.ontap(() => { - Plugins.Share.share({ url: gameApi.publicUrl(ctrl.data) }) + Plugins.LiShare.share({ url: gameApi.publicUrl(ctrl.data) }) }) }, [i18n('shareGameURL')]) }, @@ -43,7 +43,7 @@ export default { handleXhrError(err) throw err }) - .then((PGN: string) => Plugins.Share.share({ text: PGN })) + .then((PGN: string) => Plugins.LiShare.share({ text: PGN })) } return ( - diff --git a/src/ui/training/TrainingCtrl.ts b/src/ui/training/TrainingCtrl.ts index f3a56fe977..4440d05b0c 100644 --- a/src/ui/training/TrainingCtrl.ts +++ b/src/ui/training/TrainingCtrl.ts @@ -208,7 +208,7 @@ export default class TrainingCtrl implements PromotingInterface { } public share = () => { - Plugins.Share.share({ url: `https://lichess.org/training/${this.data.puzzle.id}` }) + Plugins.LiShare.share({ url: `https://lichess.org/training/${this.data.puzzle.id}` }) } public goToAnalysis = () => {