diff --git a/app/assets/stylesheets/components/_answerbox.scss b/app/assets/stylesheets/components/_answerbox.scss index d13f672f..c45dc613 100644 --- a/app/assets/stylesheets/components/_answerbox.scss +++ b/app/assets/stylesheets/components/_answerbox.scss @@ -61,4 +61,25 @@ } } } + + &__actions { + text-align: right; + justify-content: space-between; + padding-top: 10px; + + @include media-breakpoint-up('sm') { + justify-content: flex-end; + padding-top: 0; + } + } + + .card-body { + padding-bottom: .6rem; + } +} + +body:not(.cap-web-share) { + .answerbox__action[name="ab-share"] { + display: none; + } } \ No newline at end of file diff --git a/app/javascript/packs/application.ts b/app/javascript/packs/application.ts index 451567d3..bcfeddc4 100644 --- a/app/javascript/packs/application.ts +++ b/app/javascript/packs/application.ts @@ -1,3 +1,5 @@ import start from '../retrospring/common'; +import initAnswerbox from '../retrospring/features/answerbox/index'; start(); +document.addEventListener('turbolinks:load', initAnswerbox); diff --git a/app/javascript/retrospring/features/answerbox/index.ts b/app/javascript/retrospring/features/answerbox/index.ts new file mode 100644 index 00000000..45c8cd68 --- /dev/null +++ b/app/javascript/retrospring/features/answerbox/index.ts @@ -0,0 +1,17 @@ +import registerEvents from "retrospring/utilities/registerEvents"; +import {createShareEvent} from "./share"; + +export default (): void => { + if ('share' in navigator) { + document.body.classList.add('cap-web-share'); + const entries: NodeList = document.querySelectorAll('.answerbox:not(.js-initialized)'); + + entries.forEach((element: HTMLElement) => { + registerEvents([ + { type: 'click', target: element.querySelector('[name=ab-share]'), handler: createShareEvent(element) } + ]); + + element.classList.add('js-initialized'); + }); + } +} diff --git a/app/javascript/retrospring/features/answerbox/share.ts b/app/javascript/retrospring/features/answerbox/share.ts new file mode 100644 index 00000000..6d74815e --- /dev/null +++ b/app/javascript/retrospring/features/answerbox/share.ts @@ -0,0 +1,11 @@ +import noop from 'retrospring/utilities/noop'; + +export function createShareEvent(answerbox: HTMLElement): () => void { + return function (): void { + navigator.share({ + url: answerbox.querySelector('.answerbox__answer-date > a, a.answerbox__permalink').href + }) + .then(noop) + .catch(noop) + } +} diff --git a/app/javascript/retrospring/utilities/noop.ts b/app/javascript/retrospring/utilities/noop.ts new file mode 100644 index 00000000..85f1db46 --- /dev/null +++ b/app/javascript/retrospring/utilities/noop.ts @@ -0,0 +1,3 @@ +export default (): void => { + // do nothing +} diff --git a/app/javascript/retrospring/utilities/registerEvents.ts b/app/javascript/retrospring/utilities/registerEvents.ts new file mode 100644 index 00000000..a0991cce --- /dev/null +++ b/app/javascript/retrospring/utilities/registerEvents.ts @@ -0,0 +1,17 @@ +interface EventDef { + type: string; + target: Node | NodeList; + handler: EventListenerOrEventListenerObject; +} + +export default function registerEvents(events: EventDef[]): void { + events.forEach(event => { + if (event.target instanceof NodeList) { + event.target.forEach(element => { + element.addEventListener(event.type, event.handler); + }); + } else if (event.target instanceof Node) { + event.target.addEventListener(event.type, event.handler); + } + }); +} \ No newline at end of file diff --git a/app/views/answerbox/_actions.haml b/app/views/answerbox/_actions.haml index 133a3521..3c8eadd3 100644 --- a/app/views/answerbox/_actions.haml +++ b/app/views/answerbox/_actions.haml @@ -16,6 +16,8 @@ %button.btn.btn-link.answerbox__action{ type: :button, name: 'ab-comments', data: { a_id: a.id, state: :hidden } } %i.fa.fa-fw.fa-comments %span{ id: "ab-comment-count-#{a.id}" }= a.comment_count +%button.btn.btn-link.answerbox__action{ type: :button, name: 'ab-share' } + %i.fa.fa-fw.fa-share-alt{ title: 'Share' } - if user_signed_in? .btn-group %button.btn.btn-default.btn-sm.dropdown-toggle{ data: { toggle: :dropdown }, aria: { expanded: false } } diff --git a/app/views/application/_answerbox.haml b/app/views/application/_answerbox.haml index 1f427b7d..e33da4b8 100644 --- a/app/views/application/_answerbox.haml +++ b/app/views/application/_answerbox.haml @@ -16,7 +16,7 @@ = markdown a.content - if @user.nil? .row - .col.col-sm-4.col-md-6.text-left.text-muted + .col-sm-6.text-left.text-muted .media .pull-left %a{ href: show_user_profile_path(a.user.screen_name) } @@ -26,14 +26,14 @@ = raw t('views.answerbox.answered', hide: hidespan(t('views.answerbox.hide'), 'd-none d-sm-inline'), user: user_screen_name(a.user)) .answerbox__answer-date = link_to(raw(t('views.answerbox.time', time: time_tooltip(a))), show_user_answer_path(a.user.screen_name, a.id)) - .col.col-sm-8.col-md-6.text-right + .col-md-6.d-flex.d-md-block.answerbox__actions = render 'answerbox/actions', a: a, display_all: display_all - else .row - .col-4.col-sm-4.col-md-6.text-left.text-muted + .col-md-6.text-left.text-muted %i.fa.fa-clock-o - = link_to(raw(t('views.answerbox.time', time: time_tooltip(a))), show_user_answer_path(a.user.screen_name, a.id)) - .col-8.col-sm-8.col-md-6.text-right + = link_to(raw(t('views.answerbox.time', time: time_tooltip(a))), show_user_answer_path(a.user.screen_name, a.id), class: 'answerbox__permalink') + .col-md-6.d-md-flex.answerbox__actions = render 'answerbox/actions', a: a, display_all: display_all .card-footer{ id: "ab-comments-section-#{a.id}", style: display_all.nil? ? 'display: none' : nil } %div{ id: "ab-smiles-#{a.id}" }= render 'answerbox/smiles', a: a