From a7924087bfb6108a331cbd04ad935a33745ab6cc Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 24 Sep 2018 12:12:59 +0100 Subject: [PATCH 1/7] Add an alternative block appender when the container doesn't support the default bloock --- .../components/block-list-appender/index.js | 67 +++++++++++++++++++ .../components/block-list-appender/style.scss | 7 ++ .../editor/src/components/block-list/block.js | 2 +- .../editor/src/components/block-list/index.js | 23 ++----- .../index.js} | 0 .../test/index.js} | 2 +- .../editor/src/components/inserter/index.js | 17 +++-- packages/editor/src/style.scss | 1 + 8 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 packages/editor/src/components/block-list-appender/index.js create mode 100644 packages/editor/src/components/block-list-appender/style.scss rename packages/editor/src/components/{block-list/ignore-nested-events.js => ignore-nested-events/index.js} (100%) rename packages/editor/src/components/{block-list/test/ignore-nested-events.js => ignore-nested-events/test/index.js} (97%) diff --git a/packages/editor/src/components/block-list-appender/index.js b/packages/editor/src/components/block-list-appender/index.js new file mode 100644 index 00000000000000..3edeb1de93d6e8 --- /dev/null +++ b/packages/editor/src/components/block-list-appender/index.js @@ -0,0 +1,67 @@ +/** + * External dependencies + */ +import { last } from 'lodash'; + +/** + * WordPress dependencies + */ +import { withSelect } from '@wordpress/data'; +import { getDefaultBlockName } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import IgnoreNestedEvents from '../ignore-nested-events'; +import DefaultBlockAppender from '../default-block-appender'; +import Inserter from '../inserter'; + +function BlockListAppender( { + blockClientIds, + layout, + isGroupedByLayout, + rootClientId, + canInsertDefaultBlock, + isLocked, +} ) { + if ( isLocked ) { + return null; + } + + let defaultLayout; + if ( isGroupedByLayout ) { + defaultLayout = layout; + } + + if ( canInsertDefaultBlock ) { + return ( + + + + ); + } + + return ( +
+ +
+ ); +} + +export default withSelect( ( select, { rootClientId } ) => { + const { + getBlockOrder, + canInsertBlockType, + getTemplateLock, + } = select( 'core/editor' ); + + return { + isLocked: !! getTemplateLock( rootClientId ), + blockClientIds: getBlockOrder( rootClientId ), + canInsertDefaultBlock: canInsertBlockType( getDefaultBlockName(), rootClientId ), + }; +} )( BlockListAppender ); diff --git a/packages/editor/src/components/block-list-appender/style.scss b/packages/editor/src/components/block-list-appender/style.scss new file mode 100644 index 00000000000000..2d94f1c5dd3c5d --- /dev/null +++ b/packages/editor/src/components/block-list-appender/style.scss @@ -0,0 +1,7 @@ +.block-list-appender { + display: flex; + align-items: center; + justify-content: center; + padding: 10px; + border: 1px dotted $light-gray-500; +} diff --git a/packages/editor/src/components/block-list/block.js b/packages/editor/src/components/block-list/block.js index e417996f4e01a7..04850e6f590c79 100644 --- a/packages/editor/src/components/block-list/block.js +++ b/packages/editor/src/components/block-list/block.js @@ -43,7 +43,7 @@ import BlockContextualToolbar from './block-contextual-toolbar'; import BlockMultiControls from './multi-controls'; import BlockMobileToolbar from './block-mobile-toolbar'; import BlockInsertionPoint from './insertion-point'; -import IgnoreNestedEvents from './ignore-nested-events'; +import IgnoreNestedEvents from '../ignore-nested-events'; import InserterWithShortcuts from '../inserter-with-shortcuts'; import Inserter from '../inserter'; import withHoverAreas from './with-hover-areas'; diff --git a/packages/editor/src/components/block-list/index.js b/packages/editor/src/components/block-list/index.js index b041dbeaedce75..093b93740b6e9e 100644 --- a/packages/editor/src/components/block-list/index.js +++ b/packages/editor/src/components/block-list/index.js @@ -8,7 +8,6 @@ import { mapValues, sortBy, throttle, - last, } from 'lodash'; import classnames from 'classnames'; @@ -17,15 +16,13 @@ import classnames from 'classnames'; */ import { Component } from '@wordpress/element'; import { withSelect, withDispatch } from '@wordpress/data'; -import { getDefaultBlockName } from '@wordpress/blocks'; import { compose } from '@wordpress/compose'; /** * Internal dependencies */ import BlockListBlock from './block'; -import IgnoreNestedEvents from './ignore-nested-events'; -import DefaultBlockAppender from '../default-block-appender'; +import BlockListAppender from '../block-list-appender'; class BlockList extends Component { constructor( props ) { @@ -194,7 +191,6 @@ class BlockList extends Component { layout, isGroupedByLayout, rootClientId, - canInsertDefaultBlock, isDraggable, } = this.props; @@ -224,15 +220,12 @@ class BlockList extends Component { isDraggable={ isDraggable } /> ) ) } - { canInsertDefaultBlock && ( - - - - ) } + + ); } @@ -247,7 +240,6 @@ export default compose( [ getMultiSelectedBlocksStartClientId, getMultiSelectedBlocksEndClientId, getBlockSelectionStart, - canInsertBlockType, } = select( 'core/editor' ); const { rootClientId } = ownProps; @@ -258,7 +250,6 @@ export default compose( [ selectionStartClientId: getBlockSelectionStart(), isSelectionEnabled: isSelectionEnabled(), isMultiSelecting: isMultiSelecting(), - canInsertDefaultBlock: canInsertBlockType( getDefaultBlockName(), rootClientId ), }; } ), withDispatch( ( dispatch ) => { diff --git a/packages/editor/src/components/block-list/ignore-nested-events.js b/packages/editor/src/components/ignore-nested-events/index.js similarity index 100% rename from packages/editor/src/components/block-list/ignore-nested-events.js rename to packages/editor/src/components/ignore-nested-events/index.js diff --git a/packages/editor/src/components/block-list/test/ignore-nested-events.js b/packages/editor/src/components/ignore-nested-events/test/index.js similarity index 97% rename from packages/editor/src/components/block-list/test/ignore-nested-events.js rename to packages/editor/src/components/ignore-nested-events/test/index.js index 48559baf29909f..533fd26d67c8f8 100644 --- a/packages/editor/src/components/block-list/test/ignore-nested-events.js +++ b/packages/editor/src/components/ignore-nested-events/test/index.js @@ -6,7 +6,7 @@ import { mount } from 'enzyme'; /** * Internal dependencies */ -import IgnoreNestedEvents from '../ignore-nested-events'; +import IgnoreNestedEvents from '../'; describe( 'IgnoreNestedEvents', () => { it( 'passes props to its rendered div', () => { diff --git a/packages/editor/src/components/inserter/index.js b/packages/editor/src/components/inserter/index.js index be1aada97c5e4f..605ba68336d513 100644 --- a/packages/editor/src/components/inserter/index.js +++ b/packages/editor/src/components/inserter/index.js @@ -88,26 +88,31 @@ class Inserter extends Component { } export default compose( [ - withSelect( ( select ) => { + withSelect( ( select, { rootClientId, layout } ) => { const { getEditedPostAttribute, getBlockInsertionPoint, getSelectedBlock, getInserterItems, + getBlockOrder, } = select( 'core/editor' ); const insertionPoint = getBlockInsertionPoint(); - const { rootClientId } = insertionPoint; + const parentId = rootClientId || insertionPoint.rootClientId; return { title: getEditedPostAttribute( 'title' ), - insertionPoint, + insertionPoint: { + rootClientId: parentId, + layout: rootClientId ? layout : insertionPoint.layout, + index: rootClientId ? getBlockOrder( rootClientId ).length : insertionPoint.index, + }, selectedBlock: getSelectedBlock(), - items: getInserterItems( rootClientId ), - rootClientId, + items: getInserterItems( parentId ), + rootClientId: parentId, }; } ), withDispatch( ( dispatch, ownProps ) => ( { onInsertBlock: ( item ) => { - const { insertionPoint, selectedBlock } = ownProps; + const { selectedBlock, insertionPoint } = ownProps; const { index, rootClientId, layout } = insertionPoint; const { name, initialAttributes } = item; const insertedBlock = createBlock( name, { ...initialAttributes, layout } ); diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index f6e6b8e586e66a..f49b64c3a3afba 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -3,6 +3,7 @@ @import "./components/block-icon/style.scss"; @import "./components/block-inspector/style.scss"; @import "./components/block-list/style.scss"; +@import "./components/block-list-appender/style.scss"; @import "./components/block-compare/style.scss"; @import "./components/block-mover/style.scss"; @import "./components/block-preview/style.scss"; From be70a907db0d95575b61cac26568b316b3d66828 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 25 Sep 2018 13:18:28 +0100 Subject: [PATCH 2/7] Tweak the appender style --- .../components/block-list-appender/index.js | 19 ++++++++++++- .../components/block-list-appender/style.scss | 15 ++++++++-- .../editor/src/components/inserter/index.js | 28 +++++++++---------- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/packages/editor/src/components/block-list-appender/index.js b/packages/editor/src/components/block-list-appender/index.js index 3edeb1de93d6e8..af5cadd98e84c8 100644 --- a/packages/editor/src/components/block-list-appender/index.js +++ b/packages/editor/src/components/block-list-appender/index.js @@ -8,6 +8,8 @@ import { last } from 'lodash'; */ import { withSelect } from '@wordpress/data'; import { getDefaultBlockName } from '@wordpress/blocks'; +import { __ } from '@wordpress/i18n'; +import { Button, Dashicon } from '@wordpress/components'; /** * Internal dependencies @@ -47,7 +49,22 @@ function BlockListAppender( { return (
- + ( + + ) } + />
); } diff --git a/packages/editor/src/components/block-list-appender/style.scss b/packages/editor/src/components/block-list-appender/style.scss index 2d94f1c5dd3c5d..a0a453f5c4ba6b 100644 --- a/packages/editor/src/components/block-list-appender/style.scss +++ b/packages/editor/src/components/block-list-appender/style.scss @@ -1,7 +1,16 @@ -.block-list-appender { +.block-list-appender > .editor-inserter { + display: block; +} + +.block-list-appender__toggle { display: flex; align-items: center; justify-content: center; - padding: 10px; - border: 1px dotted $light-gray-500; + padding: 20px; + outline: 2px dotted $light-gray-500; + width: 100%; + + &:hover { + outline: 1px solid $dark-gray-500; + } } diff --git a/packages/editor/src/components/inserter/index.js b/packages/editor/src/components/inserter/index.js index 605ba68336d513..73a971a7de5c73 100644 --- a/packages/editor/src/components/inserter/index.js +++ b/packages/editor/src/components/inserter/index.js @@ -15,6 +15,18 @@ import InserterMenu from './menu'; export { default as InserterResultsPortal } from './results-portal'; +const defaultRenderToggle = ( { onToggle, disabled, isOpen } ) => ( + +); + class Inserter extends Component { constructor() { super( ...arguments ); @@ -36,10 +48,10 @@ class Inserter extends Component { items, position, title, - children, onInsertBlock, rootClientId, disabled, + renderToggle = defaultRenderToggle, } = this.props; if ( items.length === 0 ) { @@ -54,19 +66,7 @@ class Inserter extends Component { onToggle={ this.onToggle } expandOnMobile headerTitle={ title } - renderToggle={ ( { onToggle, isOpen } ) => ( - - { children } - - ) } + renderToggle={ ( { onToggle, isOpen } ) => renderToggle( { onToggle, isOpen, disabled } ) } renderContent={ ( { onClose } ) => { const onSelect = ( item ) => { onInsertBlock( item ); From f5cd3588b3e3da3036c8a11b4bddae41494a5e75 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 25 Sep 2018 13:19:33 +0100 Subject: [PATCH 3/7] Code style tweak --- packages/editor/src/components/block-list-appender/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/editor/src/components/block-list-appender/index.js b/packages/editor/src/components/block-list-appender/index.js index af5cadd98e84c8..5ee01b1e7c1385 100644 --- a/packages/editor/src/components/block-list-appender/index.js +++ b/packages/editor/src/components/block-list-appender/index.js @@ -30,10 +30,7 @@ function BlockListAppender( { return null; } - let defaultLayout; - if ( isGroupedByLayout ) { - defaultLayout = layout; - } + const defaultLayout = isGroupedByLayout ? layout : undefined; if ( canInsertDefaultBlock ) { return ( From 8ee7b4419ff5331248d5791be58c424425ccd976 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 26 Sep 2018 08:39:41 +0100 Subject: [PATCH 4/7] Update appendder styles as suggested --- packages/editor/src/components/block-list-appender/style.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/block-list-appender/style.scss b/packages/editor/src/components/block-list-appender/style.scss index a0a453f5c4ba6b..a1eb91ed0eca77 100644 --- a/packages/editor/src/components/block-list-appender/style.scss +++ b/packages/editor/src/components/block-list-appender/style.scss @@ -6,8 +6,8 @@ display: flex; align-items: center; justify-content: center; - padding: 20px; - outline: 2px dotted $light-gray-500; + padding: $grid-size-large; + outline: 1px dashed $light-gray-500; width: 100%; &:hover { From 1feaf87b179e72014c9f8e7bacbfd56dee895f89 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 4 Oct 2018 08:59:13 -0400 Subject: [PATCH 5/7] Adding an e2e test for the alternative appender --- ....js.snap => container-blocks.test.js.snap} | 12 ++- test/e2e/specs/container-blocks.test.js | 79 +++++++++++++++++++ test/e2e/specs/inner-blocks-templates.test.js | 54 ------------- .../container-without-paragraph.php | 19 +++++ .../container-without-paragraph/index.js | 17 ++++ 5 files changed, 125 insertions(+), 56 deletions(-) rename test/e2e/specs/__snapshots__/{inner-blocks-templates.test.js.snap => container-blocks.test.js.snap} (52%) create mode 100644 test/e2e/specs/container-blocks.test.js delete mode 100644 test/e2e/specs/inner-blocks-templates.test.js create mode 100644 test/e2e/test-plugins/container-without-paragraph.php create mode 100644 test/e2e/test-plugins/container-without-paragraph/index.js diff --git a/test/e2e/specs/__snapshots__/inner-blocks-templates.test.js.snap b/test/e2e/specs/__snapshots__/container-blocks.test.js.snap similarity index 52% rename from test/e2e/specs/__snapshots__/inner-blocks-templates.test.js.snap rename to test/e2e/specs/__snapshots__/container-blocks.test.js.snap index 82e5c8a59df17e..d48bb64ef8589e 100644 --- a/test/e2e/specs/__snapshots__/inner-blocks-templates.test.js.snap +++ b/test/e2e/specs/__snapshots__/container-blocks.test.js.snap @@ -1,6 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Correctly Renders Block Icons on Inserter and Inspector InnerBlocks Template Sync Ensures blocks without locking are kept intact even if they do not match the template 1`] = ` +exports[`Container block without paragraph support ensures we can use the alternative block appender properly 1`] = ` +" + +
\\"\\"/
+ +" +`; + +exports[`InnerBlocks Template Sync Ensures blocks without locking are kept intact even if they do not match the template 1`] = ` "

Content…

@@ -16,7 +24,7 @@ exports[`Correctly Renders Block Icons on Inserter and Inspector InnerBlocks Tem " `; -exports[`Correctly Renders Block Icons on Inserter and Inspector InnerBlocks Template Sync Removes blocks that are not expected by the template if a lock all exists 1`] = ` +exports[`InnerBlocks Template Sync Removes blocks that are not expected by the template if a lock all exists 1`] = ` "

Content…

diff --git a/test/e2e/specs/container-blocks.test.js b/test/e2e/specs/container-blocks.test.js new file mode 100644 index 00000000000000..6b6735234e4aa9 --- /dev/null +++ b/test/e2e/specs/container-blocks.test.js @@ -0,0 +1,79 @@ +/** + * Internal dependencies + */ +import { + newPost, + insertBlock, + switchToEditor, + getEditedPostContent, +} from '../support/utils'; +import { activatePlugin, deactivatePlugin } from '../support/plugins'; + +describe( 'InnerBlocks Template Sync', () => { + beforeAll( async () => { + await activatePlugin( 'gutenberg-test-innerblocks-templates' ); + } ); + + beforeEach( async () => { + await newPost(); + } ); + + afterAll( async () => { + await deactivatePlugin( 'gutenberg-test-innerblocks-templates' ); + } ); + + const insertBlockAndAddParagraphInside = async ( blockName, blockSlug ) => { + const paragraphToAdd = ` + +

added paragraph

+ + `; + await insertBlock( blockName ); + await switchToEditor( 'Code' ); + await page.$eval( '.editor-post-text-editor', ( element, _paragraph, _blockSlug ) => { + const blockDelimiter = ``; + element.value = element.value.replace( blockDelimiter, _paragraph + blockDelimiter ); + }, paragraphToAdd, blockSlug ); + // press enter inside the code editor so the onChange events for the new value trigger + await page.click( '.editor-post-text-editor' ); + await page.keyboard.press( 'Enter' ); + await switchToEditor( 'Visual' ); + }; + + it( 'Ensures blocks without locking are kept intact even if they do not match the template ', async () => { + await insertBlockAndAddParagraphInside( 'Test Inner Blocks no locking', 'test/test-inner-blocks-no-locking' ); + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); + + it( 'Removes blocks that are not expected by the template if a lock all exists ', async () => { + await insertBlockAndAddParagraphInside( 'Test InnerBlocks locking all', 'test/test-inner-blocks-locking-all' ); + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); +} ); + +describe( 'Container block without paragraph support', () => { + beforeAll( async () => { + await activatePlugin( 'gutenberg-test-container-block-without-paragraph' ); + } ); + + beforeEach( async () => { + await newPost(); + } ); + + afterAll( async () => { + await deactivatePlugin( 'gutenberg-test-container-block-without-paragraph' ); + } ); + + it( 'ensures we can use the alternative block appender properly', async () => { + await insertBlock( 'Container without paragraph' ); + + // Open the specific appender used when there's no paragraph support. + await page.click( '.editor-inner-blocks .block-list-appender .block-list-appender__toggle' ); + + // Insert an image block + await page.click( '.editor-inserter__results button[aria-label="Image"]' ); + + // Check the inserted content + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); +} ); diff --git a/test/e2e/specs/inner-blocks-templates.test.js b/test/e2e/specs/inner-blocks-templates.test.js deleted file mode 100644 index f2264bef1c70a8..00000000000000 --- a/test/e2e/specs/inner-blocks-templates.test.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Internal dependencies - */ -import { - newPost, - insertBlock, - switchToEditor, - getEditedPostContent, -} from '../support/utils'; -import { activatePlugin, deactivatePlugin } from '../support/plugins'; - -describe( 'Correctly Renders Block Icons on Inserter and Inspector', () => { - beforeAll( async () => { - await activatePlugin( 'gutenberg-test-innerblocks-templates' ); - } ); - - beforeEach( async () => { - await newPost(); - } ); - - afterAll( async () => { - await deactivatePlugin( 'gutenberg-test-innerblocks-templates' ); - } ); - - describe( 'InnerBlocks Template Sync', () => { - const insertBlockAndAddParagraphInside = async ( blockName, blockSlug ) => { - const paragraphToAdd = ` - -

added paragraph

- - `; - await insertBlock( blockName ); - await switchToEditor( 'Code' ); - await page.$eval( '.editor-post-text-editor', ( element, _paragraph, _blockSlug ) => { - const blockDelimiter = ``; - element.value = element.value.replace( blockDelimiter, _paragraph + blockDelimiter ); - }, paragraphToAdd, blockSlug ); - // press enter inside the code editor so the onChange events for the new value trigger - await page.click( '.editor-post-text-editor' ); - await page.keyboard.press( 'Enter' ); - await switchToEditor( 'Visual' ); - }; - - it( 'Ensures blocks without locking are kept intact even if they do not match the template ', async () => { - await insertBlockAndAddParagraphInside( 'Test Inner Blocks no locking', 'test/test-inner-blocks-no-locking' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - - it( 'Removes blocks that are not expected by the template if a lock all exists ', async () => { - await insertBlockAndAddParagraphInside( 'Test InnerBlocks locking all', 'test/test-inner-blocks-locking-all' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - } ); -} ); diff --git a/test/e2e/test-plugins/container-without-paragraph.php b/test/e2e/test-plugins/container-without-paragraph.php new file mode 100644 index 00000000000000..2d7a20c0026054 --- /dev/null +++ b/test/e2e/test-plugins/container-without-paragraph.php @@ -0,0 +1,19 @@ + Date: Thu, 4 Oct 2018 09:47:42 -0400 Subject: [PATCH 6/7] Polish the visuals a little bit. --- .../editor/src/components/block-list-appender/style.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/block-list-appender/style.scss b/packages/editor/src/components/block-list-appender/style.scss index a1eb91ed0eca77..a31989fcc54323 100644 --- a/packages/editor/src/components/block-list-appender/style.scss +++ b/packages/editor/src/components/block-list-appender/style.scss @@ -7,10 +7,11 @@ align-items: center; justify-content: center; padding: $grid-size-large; - outline: 1px dashed $light-gray-500; + outline: $border-width dashed $dark-gray-150; width: 100%; + color: $dark-gray-500; &:hover { - outline: 1px solid $dark-gray-500; + outline: $border-width dashed $dark-gray-500; } } From 8be4f2b50053f9db7cd67da4d0f7720752f2f692 Mon Sep 17 00:00:00 2001 From: Matthew Riley MacPherson Date: Thu, 4 Oct 2018 11:47:31 -0400 Subject: [PATCH 7/7] chore: Tidy up code --- test/e2e/specs/container-blocks.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/e2e/specs/container-blocks.test.js b/test/e2e/specs/container-blocks.test.js index 6b6735234e4aa9..301f6a8cf12c92 100644 --- a/test/e2e/specs/container-blocks.test.js +++ b/test/e2e/specs/container-blocks.test.js @@ -27,14 +27,14 @@ describe( 'InnerBlocks Template Sync', () => {

added paragraph

- `; + `; await insertBlock( blockName ); await switchToEditor( 'Code' ); await page.$eval( '.editor-post-text-editor', ( element, _paragraph, _blockSlug ) => { const blockDelimiter = ``; - element.value = element.value.replace( blockDelimiter, _paragraph + blockDelimiter ); + element.value = element.value.replace( blockDelimiter, `${ _paragraph }${ blockDelimiter }` ); }, paragraphToAdd, blockSlug ); - // press enter inside the code editor so the onChange events for the new value trigger + // Press "Enter" inside the Code Editor to fire the `onChange` event for the new value. await page.click( '.editor-post-text-editor' ); await page.keyboard.press( 'Enter' ); await switchToEditor( 'Visual' ); @@ -70,10 +70,10 @@ describe( 'Container block without paragraph support', () => { // Open the specific appender used when there's no paragraph support. await page.click( '.editor-inner-blocks .block-list-appender .block-list-appender__toggle' ); - // Insert an image block + // Insert an image block. await page.click( '.editor-inserter__results button[aria-label="Image"]' ); - // Check the inserted content + // Check the inserted content. expect( await getEditedPostContent() ).toMatchSnapshot(); } ); } );