Skip to content

Commit

Permalink
Merge branch 'share-component'
Browse files Browse the repository at this point in the history
  • Loading branch information
eelco committed Jul 28, 2016
2 parents 8463a44 + f8a6d58 commit ada2943
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 36 deletions.
15 changes: 11 additions & 4 deletions extras/Studio.framer/app.coffee
@@ -1,7 +1,14 @@

# Activate Module
Framer.Metadata =
author: "Eelco Lempsink"
twitter: "@fverloop"
title: "Here's a long af title is long seri"
description: """
Our goal with Framer has always been to build a full service design tool. So while it’s been possible to view working prototypes on a mobile browser, the experience has been less than seamless.
grid = new GridComponent
size: Screen
Then, our community came to the rescue. Both Frameless by Jay Stakelon and Frames by Rafael Conde set a new standard for mobile viewing of prototypes. Inspired by their work and your feedback, we are now launching an iOS app that fully rounds out your design experience framerjs.com.
grid.renderCell = (layer) ->
layer.image = Utils.randomImage() + "?cache=#{Date.now()}"
Framer for iOS features live preview, offline use and intuitive sharing features that are protected by secure links. Paired with Framer for Mac, you now have access to a full mobile prototyping toolkit.
"""
date: "Jun 14 2016"
9 changes: 4 additions & 5 deletions extras/Studio.framer/framer/config.json
Expand Up @@ -5,13 +5,12 @@
"deviceOrientation" : 0,
"sharedPrototype" : 1,
"contentScale" : 1,
"deviceType" : "apple-iphone-6s-gold",
"deviceType" : "fullscreen",
"selectedHand" : "iphone-hands-2",
"updateDelay" : 0.3,
"deviceScale" : "fit",
"deviceScale" : 1,
"foldedCodeRanges" : [

],
"orientation" : 0,
"fullScreen" : false
}
"orientation" : 0
}
123 changes: 98 additions & 25 deletions framer/Components/ShareComponent.coffee
Expand Up @@ -6,15 +6,13 @@ class ShareLayer extends Layer
defaultProps =
backgroundColor: null
width: options.parent.width if options and options.parent
ignoreEvents: false
style:
fontFamily: "Roboto, Helvetica Neue, Helvetica, Arial, sans-serif"
fontSize: "14px"
color: "#111"
webkitUserSelect: "text"
lineHeight: "1"
webkitFontSmoothing: "antialiased";
webkitUserSelect: "text"
userSelect: "text"

@props = _.merge(defaultProps, options)

Expand All @@ -25,6 +23,7 @@ class Button extends ShareLayer

defaultProps =
height: 33
ignoreEvents: false
style:
fontFamily: "Roboto, Helvetica Neue, Helvetica, Arial, sans-serif"
fontWeight: "500"
Expand All @@ -36,14 +35,19 @@ class Button extends ShareLayer

@props = _.merge(defaultProps, options)

@states.add hover: opacity: .8
@states.animationOptions =
time: .3

@onMouseOver ->
@style.cursor = "pointer"
@opacity = .9
@states.switch('hover')

@onMouseOut ->
@opacity = 1
@states.switch('default')

@onClick -> window.open(options.url)
@onClick -> window.open(options.url, "_blank")

# Share component
class ShareComponent
Expand All @@ -57,18 +61,18 @@ class ShareComponent
minAvailableSpace: 300
minAvailableSpaceFullScreen: 500
fixed: false
maxDescriptionLength: 135
maxDescriptionLength: 145

@render()
@_startListening()
@_checkData()
@render() if !Utils.isMobile()

render: ->
@_renderSheet()
@_renderToggleButtons()
@_renderCTA()
@_renderInfo()
@_renderDescription() if @shareInfo.description
@_renderDate()
@_renderDate() if @shareInfo.openInFramerURL and @shareInfo.date
@_renderButtons() if @shareInfo.openInFramerURL

# Evaluate content and set height accordingly
Expand All @@ -79,6 +83,23 @@ class ShareComponent
Utils.delay .1, =>
@_calculateAvailableSpace()

@_startListening()

_checkData: ->

# Twitter handle
if @shareInfo.twitter and @shareInfo.twitter.charAt(0) is "@"
@shareInfo.twitter = @shareInfo.twitter.substring(1)

# Truncate title if too long
truncate = (str, n) ->
str.substr(0, n-1).trim() + "…"

if @shareInfo.twitter and @shareInfo.title.length > 26
@shareInfo.title = truncate(@shareInfo.title, 26)
else if @shareInfo.title.length > 34
@shareInfo.title = truncate(@shareInfo.title, 34)

# Render main sheet
_renderSheet: ->
@sheet = new Layer
Expand Down Expand Up @@ -149,14 +170,20 @@ class ShareComponent
textAlign: "center"
fontSize: "18px"

ctaLink = new ShareLayer
@_enableUserSelect(ctaSlogan)

ctaLink = new Button
url: "http://framerjs.com/?utm_source=share.framerjs.com&utm_medium=banner&utm_campaign=product"
parent: @cta
y: ctaSlogan.y + 24
height: 30
height: 16
width: 120
x: Align.center()
html: "Try it for free now"
style:
textAlign: "center"
color: "#00AAFF"
padding: 0;

# Render info section
_renderInfo: ->
Expand All @@ -174,26 +201,29 @@ class ShareComponent

@credentialsTitle = new ShareLayer
parent: @credentials
width: @credentials.width - 50
height: 18
html: @shareInfo.title or fallbackTitle
style:
fontWeight: "500"

@_enableUserSelect(@credentialsTitle)
@credentialsTitle.width = @credentials - 50 if @shareInfo.twitter

# Check what info is available and render layers accordingly
showAuthor = (content = @shareInfo.author) =>
@credentials.height = 40
@credentialsTitle.y = 4

@credentialsAuthor = new ShareLayer
parent: @credentials
width: @credentials.width - 50
html: content
y: @credentialsTitle.maxY
height: 18
style:
color: "#808080"

@_enableUserSelect(@credentialsAuthor)
@credentialsAuthor.width = @credentials - 50 if @shareInfo.twitter
@_showPointer(@credentialsAuthor)

# Check if avatar is available
Expand Down Expand Up @@ -222,7 +252,7 @@ class ShareComponent

# If author name isn't available, fallback to Twitter handle
name = if @shareInfo.author then @shareInfo.author else "@#{@shareInfo.twitter}"
showAuthor("<a href='http://twitter.com/#{@shareInfo.twitter}' style='text-decoration: none;'>#{name}</a>")
showAuthor("<a href='http://twitter.com/#{@shareInfo.twitter}' style='text-decoration: none; -webkit-user-select: auto;' target='_blank'>#{name}</a>")

# If there's no twitter handle, show plain author name
if @shareInfo.author and !@shareInfo.twitter
Expand All @@ -245,19 +275,33 @@ class ShareComponent
color: "#999"
letterSpacing: ".2px"

_enableUserSelect: (layer) ->

if !layer.html then layer.html = ""
layer._elementHTML.style["-webkit-user-select"] = "auto"
layer._elementHTML.style["cursor"] = "auto"

_renderDescription: ->

# See if there are any url's in the description and wrap them in anchor tags. Make sure linebreaks are wrapped in <br/ >'s.'
parseDescription = (text) ->
urlRegex = /(https?:\/\/[^\s]+)/g
urlRegex = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi
httpRegex = /^((http|https):\/\/)/
lineBreakRegex = /(?:\r\n|\r|\n)/g

urlified = text.replace urlRegex, (url) ->
'<a href="' + url + '">' + url + '</a>'

if !httpRegex.test(url)
href = "//#{url}"
else
href = url

"<a href='#{href}' style='-webkit-user-select: auto' target='_blank'>#{url}</a>"

urlified.replace lineBreakRegex, '<br />'

@description = new Layer
ignoreEvents: false
parent: @info
y: @credentials.maxY + 10
backgroundColor: null
Expand All @@ -266,6 +310,8 @@ class ShareComponent
wordWrap: "break-word"
color: "#111"

@_enableUserSelect(@description)

descriptionStyle =
fontSize: "14px"
fontFamily: "Roboto"
Expand All @@ -278,22 +324,36 @@ class ShareComponent
{width: "#{@description.width}"}
)

descriptionClickRegister = (e) ->
@descriptionStartX = e.x
@descriptionStartY = e.y

descriptionClickCompare = (e) ->
if @descriptionStartX is e.x and @descriptionStartY is e.y
showFullDescription()

showFullDescription = =>

@options.truncated = false

@description.height = @descriptionSize.height
@description.html = parseDescription(@shareInfo.description)

@date.y = @description.maxY + 16
@buttons.y = @date.maxY + 20
if @shareInfo.openInFramerURL
@date.y = @description.maxY + 16
@buttons.y = @date.maxY + 20

@_updateHeight()
@_calculateAvailableSpace()

@description.onMouseMove =>
@description.style =
cursor: "default"

# Remove events when description is shown to make links clickable
@description.off Events.TapStart, descriptionClickRegister
@description.off Events.TapEnd, descriptionClickCompare

if @shareInfo.description.length > @options.maxDescriptionLength

@options.truncated = true
Expand All @@ -311,13 +371,16 @@ class ShareComponent
@description.html = parseDescription(@options.shortDescription)

@_showPointer(@description)
@description.onClick -> showFullDescription()

# Selecting text also triggers a click event to counter this
# we compare the TapStart and TapEnd positions
@description.on Events.TapStart, descriptionClickRegister
@description.on Events.TapEnd, descriptionClickCompare

else
@description.height = @descriptionSize.height
@description.html = parseDescription(@shareInfo.description)


_renderButtons: ->
@buttons = new ShareLayer
height: 33
Expand All @@ -334,7 +397,7 @@ class ShareComponent
backgroundColor: "00AAFF"

@buttonFacebook = new Button
url: "http://www.facebook.com"
url: "https://www.facebook.com/sharer/sharer.php?u=#{window.location.href}"
parent: @buttons
borderWidth: 1
borderColor: "#D5D5D5"
Expand All @@ -353,7 +416,9 @@ class ShareComponent
backgroundImage: "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAABGdBTUEAALGPC/xhBQAAAO1JREFUOBFjZMABWltbJX///l0GlDYAYg1GRkZxIP3n////P4E0EyOQwABNTU05QAVtQMyLIQkVwNDY3Nzs9vfv3524NMDEmWAMED1z5kyuf//+zUEWw8VG0fjq1SsnoPNkcSlGFmdB5gA16SHzQWxgoPxnZma2UVNTOxkWFvYXJo+uUQwmAaOBhn2tqak5BuPDaBSnAhXJwySQaB4kNpyJohEoqgCXIcAgWyNjQ0PDfwKGY0gDA+w5uo0YirAJAMPiLFkagTaeIUsjExMTeTaCNGIkcmyBBRTDUEeWU0EBNqoRW7KBio0GDi0CBwAHJ0YrwGtXbwAAAABJRU5ErkJggg==')"

@buttonTwitter = new Button
url: "http://www.twitter.com"
url: """
https://twitter.com/home?status=Check%20out%20my%20design%20made%20in%20%40framerjs%20%E2%80%94%20#{window.location.href}
"""
parent: @buttons
borderWidth: 1
borderColor: "#D5D5D5"
Expand Down Expand Up @@ -396,13 +461,21 @@ class ShareComponent
@sheet.height = canvasHeight

# Make the description scrollable
verticalSpace = @sheet.height - @cta.height - @credentials.height - @buttons.height - @date.height - 95
verticalSpace = @sheet.height - @cta.height - @credentials.height

if @shareInfo.openInFramerURL
verticalSpace -= @buttons.height
verticalSpace -= @date.height
verticalSpace -= 95
else
verticalSpace -= 36

@description.height = verticalSpace
@description.style.overflow = "scroll"

@date.y = @description.maxY + 20
@buttons.y = @date.maxY + 20
if @shareInfo.openInFramerURL
@date.y = @description.maxY + 20
@buttons.y = @date.maxY + 20

if @description and canvasHeight > @sheet.maxHeight
@sheet.height = @sheet.maxHeight
Expand Down
2 changes: 1 addition & 1 deletion framer/Extras/ShareInfo.coffee
Expand Up @@ -10,7 +10,7 @@ class ShareInfo extends BaseClass

Utils.delay 0, =>
@context.run ->
share = new ShareComponent(Framer.Metadata)
share = new ShareComponent(Framer.Info)

destroy: ->
@context.destroy()
Expand Down
3 changes: 2 additions & 1 deletion framer/Framer.coffee
Expand Up @@ -51,7 +51,8 @@ Framer.GestureInputRecognizer = new (require "./GestureInputRecognizer").Gesture
Framer.Version = require "../build/Version"
Framer.Loop = new Framer.AnimationLoop()

Framer.Metadata = {}
# Metadata
Framer.Info = {}

window.Framer = Framer if window

Expand Down

0 comments on commit ada2943

Please sign in to comment.