Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…ities

* 'master' of https://github.com/AndyDentFree/im-plausibilities:
  readme update
  imUrlDatAppSUI - Fix app sender and include refactoring from imUrlDataApp (still broken) MessagesViewController.swift - Mood enum moved out to its own file - local let moodKey moved to Mood enum - Mood subscript added
  imUrlDataApp renamed MessageComposingHelper file to match class
  imUrlDataApp - Fix app sender to send last-tapped emoji (was always "happy") MessagesViewController.swift - Mood enum moved out to its own file - local let moodKey moved to Mood enum - subscript added
  imUrlDataApp - Refactor Message Sending from App for easy reuse in other sample ViewController.swift - var messager added - displayMessageInterface and messageComposeViewController moved to MessageComposerInApp - viewDidLoad use messager to set state if !canSendText - onAppSendButton call messager to display
  imUrlDataAppSUI - Adding Messenger extension Target showing SwiftUI
  Adding Messenger extension Target imUrlDataAppSUI IM project target added as iMessage extension
  • Loading branch information
AndyDentFree committed Aug 22, 2022
2 parents f2155cc + f61ef1f commit 45c8a37
Show file tree
Hide file tree
Showing 23 changed files with 1,190 additions and 143 deletions.
4 changes: 3 additions & 1 deletion imStickered/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ Copied from webFromIM & reworked.

See the overall rationale in the [readme in the parent folder](../README.md).

This sample explores using [Snap's StickerKit][SK] as it allows for using Stickers without login. There will also be a sample exploring [LoginKit] and BitMoji. This simpler one seeks to show the ability to pull in stickers only in the iMessage app extension without worrying about deeplinking callback issues.
This sample explores using [Snap's StickerKit][SK] as it allows for using Stickers without login. There may also be a sample exploring [LoginKit] and BitMoji. This simpler one seeks to show the ability to pull in stickers only in the iMessage app extension without worrying about deeplinking callback issues.

Similar

Note that this is a sample app under the MIT License (as per `../LICENSE`) so feel free to copy to build your own apps on top of the code here. I may have taken minor shortcuts or engineering approaches inadequate for production apps.

Expand Down

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions imUrlDataApp/Common/Mood.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// Mood.swift
// imUrlDataApp
//
// Created by AndyDent on 6/8/2022.
// Copyright © 2022 Touchgram Pty Ltd. All rights reserved.
//

import Foundation

enum Mood : String, CaseIterable {
case happy
case quizzical
case distraught
case angry

static let moodKey = "mood"

static subscript(i: Int) -> Mood? {
guard i >= 0 && i < 4 else {return nil}
return Mood.allCases[i]
}

}
2 changes: 1 addition & 1 deletion imUrlDataApp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Note another strong reason to have the companion app installable is to support I

Apple provide [MFMessageComposeViewController](https://developer.apple.com/documentation/messageui/mfmessagecomposeviewcontroller) so you can compose messages inside an app. This is documented as being mostly about sending text **but** you can also assign the `message` property which is an `MSMessage`. The documentation misleadingly says _To display your iMessage app, create and assign an MSMessage object to this property._ but there's no such automatic behaviour.

What _does_ seem to happen, magically behind the scene, is that the iMessage delivered is typed for the iMessage Extension App bundled with your sending app. ie: you can only use this technique when there's an extension.
What _does_ seem to happen, magically behind the scene, is that the iMessage delivered is typed for the iMessage Extension App bundled with your sending app. ie: **you can only use this technique when there's an extension.**


## Project Structure
Expand Down
39 changes: 38 additions & 1 deletion imUrlDataApp/imUrlDataApp Code Change Diary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,41 @@ ViewController.swift
- add protocol MFMessageComposeViewControllerDelegate
- appSendButton added and connected
- onAppSendButton added to invoke displayMessageInterface
- displayMessageInterface added
- displayMessageInterface added


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Refactor Message Sending from App for easy reuse in other sample
2022-08-05

ViewController.swift
- var messager added
- displayMessageInterface and messageComposeViewController moved to MessageComposerInApp
- viewDidLoad use messager to set state if !canSendText
- onAppSendButton call messager to display

MessageComposerInApp.swift
- added as NSObject, MFMessageComposeViewControllerDelegate


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Fix app sender to send last-tapped emoji (was always "happy")
2022-08-06

MessagesViewController.swift
- Mood enum moved out to its own file
- local let moodKey moved to Mood enum
- subscript added

MessageComposingHelper
- displayMessageInterface take a mood param instead of using hardcoded strings

ViewController
- onAppSendButton pass mood to displayMessageInterface
- buttonFor(mood) helper added
- tap(mood) added
- viewDidLoad
- call tap(mood) to get highlighted
- set button isEnabled state (now we're not using them to toggle back on, should only be tappable when enabled)
- onHappy…Angry - call tap(mood:) instead of toggle, so tapping emoji sets the one to send
- matchButtonsToToggles - set isEnabled state
13 changes: 2 additions & 11 deletions imUrlDataApp/imUrlDataApp IM/MessagesViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ import UIKit
import os
import Messages


enum Mood : String {
case happy
case quizzical
case distraught
case angry
}

class MessagesViewController: MSMessagesAppViewController {

@IBOutlet fileprivate weak var happyBtn: UIButton!
Expand All @@ -27,7 +19,6 @@ class MessagesViewController: MSMessagesAppViewController {
@IBOutlet fileprivate weak var statusLabel: UILabel!

var receivedMood:Mood? = nil
let moodKey = "mood"
let responseKey = "respondingTo"
let senderTimestampKey = "sentTS"
var enabled = [Bool]()
Expand Down Expand Up @@ -62,7 +53,7 @@ class MessagesViewController: MSMessagesAppViewController {
}
os_log("hasIncoming parsing message")
guard let comps = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return }
if let msgMood = comps.queryItems?.first(where: { $0.name == moodKey })?.value {
if let msgMood = comps.queryItems?.first(where: { $0.name == Mood.moodKey })?.value {
if let parsedMood = Mood(rawValue: msgMood) {
receivedMood = parsedMood
statusLabel.text = "Respond to '\(msgMood)'"
Expand Down Expand Up @@ -155,7 +146,7 @@ class MessagesViewController: MSMessagesAppViewController {
fatalError("Invalid base URL")
}
var qi = [
URLQueryItem(name:moodKey, value:mood.rawValue)
URLQueryItem(name: Mood.moodKey, value:mood.rawValue)
]
if receivedMood != nil {
qi.append(URLQueryItem(name:responseKey, value:receivedMood!.rawValue))
Expand Down
10 changes: 10 additions & 0 deletions imUrlDataApp/imUrlDataApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
4201A9D521F0763B0043E369 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4201A9D321F0763B0043E369 /* Main.storyboard */; };
4201A9D721F0763C0043E369 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4201A9D621F0763C0043E369 /* Assets.xcassets */; };
4201A9DA21F0763C0043E369 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4201A9D821F0763C0043E369 /* LaunchScreen.storyboard */; };
42089152289E15FB0036C790 /* Mood.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42089151289E15FB0036C790 /* Mood.swift */; };
42089153289E15FB0036C790 /* Mood.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42089151289E15FB0036C790 /* Mood.swift */; };
42199E9021F1CA5600D4377E /* Messages.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42199E8F21F1CA5600D4377E /* Messages.framework */; };
42199E9321F1CA5600D4377E /* MessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42199E9221F1CA5600D4377E /* MessagesViewController.swift */; };
42199E9621F1CA5600D4377E /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 42199E9421F1CA5600D4377E /* MainInterface.storyboard */; };
42199E9821F1CA5700D4377E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 42199E9721F1CA5700D4377E /* Assets.xcassets */; };
42199E9C21F1CA5700D4377E /* imUrlDataApp IM.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 42199E8D21F1CA5600D4377E /* imUrlDataApp IM.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
42199EA521F22CA400D4377E /* SharedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42199EA421F22CA400D4377E /* SharedData.swift */; };
42199EA621F22CA400D4377E /* SharedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42199EA421F22CA400D4377E /* SharedData.swift */; };
4276811F289D2D8B008FDF6C /* MessageComposingHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4276811E289D2D8B008FDF6C /* MessageComposingHelper.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -53,6 +56,7 @@
4201A9D621F0763C0043E369 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4201A9D921F0763C0043E369 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
4201A9DB21F0763C0043E369 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
42089151289E15FB0036C790 /* Mood.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mood.swift; sourceTree = "<group>"; };
42199E8D21F1CA5600D4377E /* imUrlDataApp IM.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "imUrlDataApp IM.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
42199E8F21F1CA5600D4377E /* Messages.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Messages.framework; path = System/Library/Frameworks/Messages.framework; sourceTree = SDKROOT; };
42199E9221F1CA5600D4377E /* MessagesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesViewController.swift; sourceTree = "<group>"; };
Expand All @@ -62,6 +66,7 @@
42199EA121F22A1300D4377E /* imUrlDataApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = imUrlDataApp.entitlements; sourceTree = "<group>"; };
42199EA221F22A1700D4377E /* imUrlDataApp IM.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "imUrlDataApp IM.entitlements"; sourceTree = "<group>"; };
42199EA421F22CA400D4377E /* SharedData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedData.swift; sourceTree = "<group>"; };
4276811E289D2D8B008FDF6C /* MessageComposingHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposingHelper.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -113,6 +118,7 @@
4201A9D621F0763C0043E369 /* Assets.xcassets */,
4201A9D821F0763C0043E369 /* LaunchScreen.storyboard */,
4201A9DB21F0763C0043E369 /* Info.plist */,
4276811E289D2D8B008FDF6C /* MessageComposingHelper.swift */,
);
path = imUrlDataApp;
sourceTree = "<group>";
Expand Down Expand Up @@ -141,6 +147,7 @@
isa = PBXGroup;
children = (
42199EA421F22CA400D4377E /* SharedData.swift */,
42089151289E15FB0036C790 /* Mood.swift */,
);
path = Common;
sourceTree = "<group>";
Expand Down Expand Up @@ -258,8 +265,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
42089152289E15FB0036C790 /* Mood.swift in Sources */,
42199EA521F22CA400D4377E /* SharedData.swift in Sources */,
4201A9D221F0763B0043E369 /* ViewController.swift in Sources */,
4276811F289D2D8B008FDF6C /* MessageComposingHelper.swift in Sources */,
4201A9D021F0763B0043E369 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -269,6 +278,7 @@
buildActionMask = 2147483647;
files = (
42199EA621F22CA400D4377E /* SharedData.swift in Sources */,
42089153289E15FB0036C790 /* Mood.swift in Sources */,
42199E9321F1CA5600D4377E /* MessagesViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
65 changes: 65 additions & 0 deletions imUrlDataApp/imUrlDataApp/MessageComposingHelper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// MessageComposerInApp.swift
// imUrlDataApp
//
// Created by AndyDent on 5/8/2022.
// Copyright © 2022 Touchgram Pty Ltd. All rights reserved.
//

import Foundation
import MessageUI
import Messages

class MessageComposingHelper: NSObject, MFMessageComposeViewControllerDelegate {

func canSendText() -> Bool {
MFMessageComposeViewController.canSendText()
}

func displayMessageInterface(onVC vc: UIViewController, mood:Mood) {
let composeVC = MFMessageComposeViewController()
composeVC.messageComposeDelegate = self

// Configure the fields of the interface.
composeVC.recipients = ["123456"]
composeVC.body = "Sending a custom message"
//
/*
According to
https://developer.apple.com/documentation/messageui/mfmessagecomposeviewcontroller/2213331-message
If your app has an iMessage app extension, you can display your iMessage app within the message compose view, just as you would in the Messages app. To display your iMessage app, create and assign an MSMessage object to this property.

By default, this property is set to nil.
*/
if #available(iOS 10, *) { // necessary if clause to make XCode happy to use composeVC.message
let message = MSMessage(session: MSSession())
// fake building a smiley using hardcoded stuff to match MessagesViewController.send
guard var urlComps = URLComponents(string:"data:,") else {
fatalError("Invalid base URL")
}
urlComps.queryItems = [URLQueryItem(name: Mood.moodKey, value:mood.rawValue)]
message.url = urlComps.url
composeVC.message = message
}

// Present the view controller modally.
if MFMessageComposeViewController.canSendText() {
vc.present(composeVC, animated: true, completion: nil)
} else {
print("Can't send messages.")
}
}

//MARK - conform to MFMessageComposeViewControllerDelegate
func messageComposeViewController(_ controller: MFMessageComposeViewController,
didFinishWith result: MessageComposeResult) {
// Check the result or perform other tasks.
let msgStr = result == .cancelled ?
"Cancelled" : result == .failed ?
"Failed" :
"Sent"
print(msgStr)
// Dismiss the message compose view controller.
controller.dismiss(animated: true, completion: nil)
}
}
Loading

0 comments on commit 45c8a37

Please sign in to comment.