Skip to content

Instantly share code, notes, and snippets.

@zo0m
Last active February 19, 2016 23:34
Show Gist options
  • Save zo0m/df6af674c9b3d3b84579 to your computer and use it in GitHub Desktop.
Save zo0m/df6af674c9b3d3b84579 to your computer and use it in GitHub Desktop.
Simple Appecelerator Titanium IOS / Android Mobile Application
args = arguments or [{}]
args = args[0]
humanizeDuration = (eventDuration)->
eventMDuration = Alloy.Globals.Moment.duration(eventDuration, 'seconds');
eventDurationString = ""
if eventMDuration.days() > 0
eventDurationString += " " + Alloy.Globals.Moment.duration(eventMDuration.days(), 'days').humanize()
if eventMDuration.hours() > 0
eventDurationString += " " + Alloy.Globals.Moment.duration(eventMDuration.hours(), 'hours').humanize()
if eventMDuration.minutes() > 0
eventDurationString += " " + Alloy.Globals.Moment.duration(eventMDuration.minutes(), 'minutes').humanize()
eventDurationString.trim()
setupEventStartDateTimeContainer = (event)->
todayMoment = Alloy.Globals.Moment()
startTimeMoment = Alloy.Globals.Moment(event.start_time)
doesItStartsToday = todayMoment.format(Alloy.Globals.Const.DEFAULT_DATE_KEY) is startTimeMoment.format(Alloy.Globals.Const.DEFAULT_DATE_KEY)
Ti.API.debug "doesItStartsToday = #{doesItStartsToday}"
if doesItStartsToday
$.eventDateLbl.text = "Cегодня #{startTimeMoment.format '(dd.)'}"
$.eventDateSubLbl.text = null
$.eventTimeLbl.text = 'в ' + startTimeMoment.format 'HH:mm'
$.eventTimeSubLbl.height = 40
$.eventTimeSubLbl.text = "(#{startTimeMoment.fromNow()})"
$.eventTimeSubLbl.height = Ti.UI.SIZE
else
$.eventDateLbl.text = startTimeMoment.format 'DD MMMM (dd.)'
$.eventDateSubLbl.text = "(#{Alloy.Globals.Moment(startTimeMoment).startOf('day').fromNow()})"
$.eventTimeLbl.text = 'в ' + startTimeMoment.format 'HH:mm'
$.eventTimeSubLbl.text = null
$.eventTimeSubLbl.height = 0
if event.duration
endTimeMoment = startTimeMoment.add(event.duration, 'seconds')
$.eventTimeToLbl.text = "до #{endTimeMoment.format 'HH:mm'}"
$.eventTimeToLbl.height = 40
$.eventTimeToLbl.height = Ti.UI.SIZE
else
$.eventTimeToLbl.height = 0
$.eventTimeToLbl.text = null
setupEventTitleContainer = (event)->
$.eventNameLbl.text = event.name
eventTypesByAlias = Alloy.Globals.EventTypes or {}
eventTypeName = eventTypesByAlias[event.custom_fields.event_type]
eventTypeName = eventTypeName.name if eventTypeName
$.eventTypeLbl.text = if eventTypeName then "|#{eventTypeName}|" else ''
priceValue = Alloy.Globals.getPriceStringFromEvent(event)
if priceValue
$.eventPriceLbl.height = Ti.UI.SIZE
$.eventPriceLbl.text = priceValue
else
$.eventPriceLbl.height = 0
setupMultiplyInfos = (items = [], infoRow, container, idPrefix, calculateText, menuAction, menuField)->
if items.length > 0
container.removeAllChildren()
infoRow.show()
infoRow.height = 5 + 50 * items.length
infoRow.top = 5
for value, index in items
itemContainer = Ti.UI.createView
left : 0
top : 0 #(index > 0) ? 5 : 0
height : 30
width : Ti.UI.SIZE
layout : 'composite'
itemLbl = Ti.UI.createLabel
id : "#{idPrefix}_#{index}"
text : calculateText value
left : 0
color : '#FFFFFF'
font :
fontFamily : Alloy.Globals.DEFAULT_FONT_FAMILY_REGULAR,
fontSize : 18
itemContainer.menuAction = menuAction
itemContainer[menuField] = value
itemContainer.add itemLbl
container.add itemContainer
itemContainer.height = Ti.UI.SIZE
Ti.API.info "added #{menuAction}.#{menuField} #{value}"
infoRow.height = Ti.UI.SIZE
else
infoRow.hide()
infoRow.height = 0
infoRow.top = 0
setupEventPlaceContainer = (event)->
$.eventPlaceNameLbl.text = event.place.name
$.eventPlaceAddressLbl.text = "#{event.place.address} (на карте)"
$.eventPlaceAddressRow.menuAction = 'map'
$.eventPlaceAddressRow.address = event.place.address
$.eventPlaceAddressRow.latitude = event.place.latitude
$.eventPlaceAddressRow.longitude = event.place.longitude
$.eventPlaceAddressLbl.height = 0;
$.eventPlaceAddressLbl.height = Ti.UI.SIZE;
setupMultiplyInfos(
event.place.custom_fields.phones
$.eventPlacePhoneRow
$.eventPlacePhonesContainer
"eventPlacePhoneLbl"
(value)-> "#{value} (позвонить)"
"phone"
"phone"
)
setupMultiplyInfos(
event.place.custom_fields.websites
$.eventPlaceSiteRow
$.eventPlaceWebsitesContainer
"eventPlaceSiteLbl"
(value)-> "#{Alloy.Globals.Utils.prettyUrl value} (открыть)"
"url"
"url"
)
setupEventOrganizatorsSection = (event)->
setupMultiplyInfos(
event.custom_fields.phones
$.eventOrgPhonesRow
$.eventOrgPhonesContainer
"eventOrgPhoneLbl"
(value)-> "#{value} (позвонить)"
"phone"
"phone"
)
setupMultiplyInfos(
event.custom_fields.websites
$.eventOrgSiteRow
$.eventOrgSitesContainer
"eventOrgSiteLbl"
(value)-> "#{Alloy.Globals.Utils.prettyUrl value} (открыть)"
"url"
"url"
)
if event.custom_fields.websites?.length > 0 or event.custom_fields.phones?.length > 0
$.eventOrganizatorsSection.height = Ti.UI.SIZE
else
$.eventOrganizatorsSection.height = 0
# ===========================================================================
# ===========================================================================
prepareController = (args = {}) ->
$.eventCardContainer.hide()
$.eventCardContainer.right = -1000
currentEvent = null
setupController = (args = {}) ->
Ti.API.info "event/card setupController "
Alloy.Globals.EventCardIsOpened = true
$.eventCardContainer.show()
$.eventCardContainer.animate
right : 0
duration : 300
event = args.event or {}
event.place or= {}
event.place.custom_fields or= {}
if currentEvent?.id is event.id
Ti.API.info "same event = #{currentEvent.id}"
currentEvent = event
else
currentEvent = event
Ti.API.info "currentEvent = #{currentEvent.id}"
setupEventStartDateTimeContainer event
setupEventTitleContainer event
setupEventPlaceContainer event
setupEventOrganizatorsSection event
$.eventDescriptionLbl.text = event.details
$.eventCardScrollView.scrollTo 0,0
Alloy.Globals.FLURY.logEvent 'events.single.show', eventId : args.event.id
# Setup
setupController(args) if !args.setup
# listeners
createOptionDialog = (event, options) ->
config =
cancel : 0
options : [
L 'opt_cancel'
]
filteredOptions = []
for option in options
if !option.hide
filteredOptions.push option
for option in filteredOptions
config.options.push(option.label)
moreDialog = Ti.UI.createOptionDialog config
moreDialog.addEventListener 'click', (selectOptionEvent) ->
if selectOptionEvent.index > 0
selectedOption = filteredOptions[selectOptionEvent.index - 1]
Ti.API.debug "{#{event.id}} ->>> action with params #{JSON.stringify selectedOption.params}"
selectedOption.action selectedOption.params
Alloy.Globals.FLURY.logEvent 'events.single.tools'
moreDialog.show()
callToNumber = (phone)->
Ti.API.debug "callToNumber : #{phone}"
Alloy.Globals.FLURY.logEvent 'events.single.tools.call', number : phone
Ti.Platform.openURL 'tel:' + phone
openBrowser = (url)->
Ti.API.debug "openBrowser : #{url}"
Alloy.Globals.FLURY.logEvent 'events.single.tools.browser', url : url
Alloy.Globals.Application.open "fullscreen", 'browser', url: url, event : currentEvent
openUrl = (url)->
Ti.API.debug "openUrl : #{url}"
Alloy.Globals.FLURY.logEvent 'events.single.tools.url', url : url
Ti.Platform.openURL url
getUrlActions = (sourceElement)->
return [
label : "Открыть #{sourceElement.url}"
action : openBrowser
params : "http://#{ Alloy.Globals.Utils.cleanUpURL sourceElement.url}"
]
copyToClipboard = (text)->
Ti.API.debug "copyToClipboard : #{text}"
Alloy.Globals.FLURY.logEvent 'events.single.tools.clipboard', text : text
Ti.UI.Clipboard.setText text
getMapActions = (sourceElement)->
return [
label : "Показать на Google Карте"
action : openBrowser
params : do ->
if (!isNaN(parseFloat(sourceElement.latitude)) and !isNaN(parseFloat(sourceElement.longitude)))
"https://maps.google.com/?q=#{sourceElement.latitude},#{sourceElement.longitude}"
else
"https://maps.google.com/search/" + Titanium.Network.encodeURIComponent("#{sourceElement.address}, Одесса, Одесская область")
,
label : "Открыть в приложении Google Maps"
action : openUrl
params : do ->
protocol = "comgooglemapsurl" #if Ti.Platform.canOpenURL('comgooglemapsurl://') then "comgooglemapsurl" else "https"
if (!isNaN(parseFloat(sourceElement.latitude)) and !isNaN(parseFloat(sourceElement.longitude)))
"#{protocol}://maps.google.com/?q=#{sourceElement.latitude},#{sourceElement.longitude}"
else
"#{protocol}://maps.google.com/search/" + Titanium.Network.encodeURIComponent("#{sourceElement.address}, Одесса, Одесская область")
hide : !(OS_IOS and Ti.Platform.canOpenURL('comgooglemapsurl://'))
,
label : "Открыть в приложении Google Maps"
action : openUrl
params : do ->
if (!isNaN(parseFloat(sourceElement.latitude)) and !isNaN(parseFloat(sourceElement.longitude)))
"http://maps.google.com/?ll=#{sourceElement.latitude},#{sourceElement.longitude}"
else
"http://maps.google.com/search/" + Titanium.Network.encodeURIComponent("#{sourceElement.address}, Одесса, Одесская область")
hide : !OS_ANDROID
,
label : "Показать в 2ГИС"
action : openBrowser
params : do ->
if (!isNaN(parseFloat(sourceElement.latitude)) and !isNaN(parseFloat(sourceElement.longitude)))
"http://2gis.ua/odessa/callout/#{sourceElement.longitude}%2C#{sourceElement.latitude}%2C18/center/#{sourceElement.longitude}%2C#{sourceElement.latitude}/zoom/17"
else
"https://2gis.ua/odessa/search/" + Titanium.Network.encodeURIComponent("Одесса, #{sourceElement.address}")
,
label : "Открыть в приложении Apple Карты"
action : openUrl
params : do ->
if (!isNaN(parseFloat(sourceElement.latitude)) and !isNaN(parseFloat(sourceElement.longitude)))
"http://maps.apple.com/?ll=#{sourceElement.latitude},#{sourceElement.longitude}"
else
"http://maps.apple.com/?q=#{Titanium.Network.encodeURIComponent("#{sourceElement.address}, Одесса, Одесская область")}"
hide : !OS_IOS
,
label : "Открыть в приложении iGO (экспериментально)"
action : (url)->
if OS_ANDROID
try
if not (openUrl url)
Alloy.Globals.Notifier.show("Ой, не получилось. У вас наверно не установлено iGO")
Alloy.Globals.Notifier.show("Это экспериментальная функция")
catch error
Alloy.Globals.Notifier.show("Ой, не получилось. У вас наверно не установлено iGO")
Alloy.Globals.Notifier.show("Это экспериментальная функция")
else
openUrl url
params : "igomyway://G#{sourceElement.latitude};#{sourceElement.longitude}"
hide : !((OS_IOS and Ti.Platform.canOpenURL('igomyway://') and sourceElement.latitude and !isNaN(parseFloat(sourceElement.latitude)) sourceElement.longitude and !isNaN(parseFloat(sourceElement.longitude))) or OS_ANDROID)
,
label : "Скопировать адрес"
action : copyToClipboard
params : sourceElement.address
]
getPhoneActions = (sourceElement)->
Ti.API.info 'getPhoneActions ' + sourceElement.phone
return [
label : "Звонок #{sourceElement.phone}"
action : callToNumber
params : sourceElement.phone
]
menuActionMap =
url : getUrlActions
map : getMapActions
phone : getPhoneActions
handleAction = (event = {})->
event.source or= {}
source = event.source.parent if !event.source.menuAction
source = source.parent if source and !source.menuAction
if currentEvent and source and source.menuAction
Ti.API.info "handleAction() :: [#{source.id}]==>#{source.menuAction}"
get____Actions = menuActionMap[source.menuAction]
actions = get____Actions source
if actions and actions.length > 0
createOptionDialog currentEvent, actions
$.eventPlaceSection.addEventListener 'click', (event)->
handleAction(event)
$.eventOrganizatorsSection.addEventListener 'click', (event)->
handleAction(event)
$.shareEvent.addEventListener 'click', (event)->
Titanium.Media.takeScreenshot (screenShotResult)->
Ti.API.info "takeScreenShot"
file = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, 'ShareEventScreenShot.jpeg'); #Ti.Filesystem.createTempFile(Titanium.Filesystem.tempDirectory)
file.write screenShotResult.media
filePath = file.nativePath
Ti.API.info "takeScreenShot #{filePath}"
if OS_IOS
docViewer = Ti.UI.iOS.createDocumentViewer url:filePath
docViewer.show animated : yes
else if OS_ANDROID
shareIntent = Ti.Android.createIntent
action: Ti.Android.ACTION_SEND,
type: "image/jpeg"
eventTypesByAlias = Alloy.Globals.EventTypes or {}
eventTypeName = eventTypesByAlias[currentEvent.custom_fields.event_type] || currentEvent.custom_fields.event_type
startTimeMoment = Alloy.Globals.Moment(currentEvent.start_time)
shareIntent.putExtra Ti.Android.EXTRA_TEXT, "#{startTimeMoment.format "DD MMM в HH:mm"} | #{eventTypeName.name} | #{currentEvent.name} | #{currentEvent.place.name}"
shareIntent.putExtraUri Ti.Android.EXTRA_STREAM, filePath
Ti.Android.currentActivity.startActivity Ti.Android.createIntentChooser(shareIntent, "Отправить событие")
# hide listeners
hideCard = ->
$.eventCardContainer.animate
right : -1000
duration : 200
, ->
$.eventCardContainer.hide()
Alloy.Globals.EventCardIsOpened = false
Alloy.Globals.FullScreenApplication.hide()
$.closeImgView.addEventListener 'click', (event)->
hideCard()
$.eventCardContainer.addEventListener 'swipe', (event)->
if event.direction == 'right'
Ti.API.info "EVENT CARD RIGHTSWIPE!"
event.cancelBubble = true
hideCard()
# Exports
exports.setupController = setupController
exports.prepareController = prepareController
class LikeService
constructor: (@globals, @cloud) ->
@likeCloud = @cloud.Likes
likePost: (postId, callbacks)->
Ti.API.debug "LikeService#likePost #{postId}"
@likeCloud.create
post_id : postId,
(likeCreateEvent) ->
if (likeCreateEvent.success)
like = likeCreateEvent.likes[0]
callbacks?.success? like
else
Ti.API.error "Error received: #{JSON.stringify likeCreateEvent}"
callbacks?.error? likeCreateEvent
removeLikeFromPost: (postId, callbacks)->
Ti.API.debug "LikeService#removeLikeFromPost #{postId}"
@likeCloud.remove
post_id : postId,
(likeCreateEvent) ->
if (likeCreateEvent.success)
callbacks?.success?()
else
Ti.API.error "Error received: #{JSON.stringify likeCreateEvent}"
callbacks?.error? likeCreateEvent
toggleLikePost: (post, callbacks)->
Ti.API.debug "LikeService#toggleLikePost #{post.id}"
callbacks or= {}
successCallback = callbacks.success
if (post.current_user_liked is true)
callbacks.success = ()->
post.current_user_liked = false
successCallback() if successCallback
@removeLikeFromPost post.id, callbacks
else
callbacks.success = (like)->
post.current_user_liked = true
successCallback like if successCallback
@likePost post.id, callbacks
module.exports = LikeService
mixin topPane
//############################### topPane
View.bg-50.h-50.w-fill.lo-c.t-0
View.w-size.h-50.lo-h.l-0
ImageView#logoImg.h-50.w-size.b-0(image='/images/logo.png')
View.w-size.h-size.lo-v.hide
Label#currentPageDateValueLbl.bold-huge.color-app
Label#currentPageDateLbl.small.color-app сегодня
View.w-size.h-50.lo-h.r-0
View#searchImgView.h-50.w-50.lo-c
ImageView.h-30.w-30(image='/images/icons/magnifying_glass.png')
View#filterImgView.h-50.w-50.lo-c
ImageView.h-30.w-30(image='/images/icons/filter_white.png')
mixin mainContainer
//############################### mainContainer
View#mainScrollContainer.bg-transparent.b-0.t-110.w-fill.lo-v.st-vertical.scrolling-enabled
View#controllerContainer.bg-transparent.w-100p.h-size.lo-vertical.t-10
mixin fullScreenContainer
//############################### fullScreenContainer
View#fullScreenContainer.hide.w-fill.h-fill.bg-transparent(zIndex="97000")
mixin roundedMainMenuBtn(id, image, label)
View(id=id).w-fill.h-size.lo-v
View.img-circle-sm.lo-c.border-app.bg-app(id=id + 'Container')
ImageView.h-40.w-40(image=image id=id + 'Image')
if label
Label(id=id + '_lbl').color-white.huge.bg-75 #{label}
mixin mainMenuButton
View#menuBtnLayout.b-10.r-10.h-60.w-60.lo-c(zIndex='96500')
+roundedMainMenuBtn("menuBtn", "/images/icons/plus.png")
// ====================================================================================
// ====================================================================================
Alloy
View#rootView.main-bg.w-fill.h-fill.lo-c.t-0
+topPane
+mainContainer
+fullScreenContainer
+mainMenuButton
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment