Skip to content

Commit

Permalink
start with apple stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon-Laux committed Jan 13, 2023
1 parent 678bca8 commit 46af766
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 2 deletions.
6 changes: 6 additions & 0 deletions _locales/_untranslated_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,11 @@
},
"donate_money_reason":{
"message": "Your support helps us to continue to improve Delta Chat."
},
"in_app_donate_no_permission": {
"message": "The user is not allowed to make in-app purchase."
},
"in_app_donate_not_availible": {
"message": "in-app donation failed to load, please conect to the internet"
}
}
16 changes: 16 additions & 0 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,19 @@ https://developer.apple.com/library/archive/documentation/Miscellaneous/Referenc

If you want to debug how many jsonrpc calls were made you can run `exp.printCallCounterResult()` in the devConsole when you have debug logging enabled.
This can be useful if you want to test your debouncing logic or compare a branch against another branch, to see if you change reduced overall jsonrpc calls.

### MacOS in app purchase stuff for donations on MacOS:

To test it you need to replace the bundle id:

```
sed -i s/com.github.Electron/chat.delta.desktop.electron/ node_modules/electron/dist/Electron.app/Contents/Info.plist
```

> note: that the `-i` option does only work with the gnu version of `sed`.

#### Useful links:

- https://help.apple.com/app-store-connect/#/devb57be10e7
- Create a Sandbox Apple ID - https://help.apple.com/app-store-connect/#/dev8b997bee1
152 changes: 152 additions & 0 deletions src/main/inAppPurchases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { inAppPurchase } from 'electron'
import { platform } from 'os'
import { getLogger } from '../shared/logger'

const log = getLogger('main/inAppDonations')

// Listen for transactions as soon as possible.
inAppPurchase.on(
'transactions-updated',
async (_event: any, transactions: Electron.Transaction[]) => {
if (!Array.isArray(transactions)) {
log.info('No Transactions to process')
return
}

// Check each transaction.
transactions.forEach(transaction => {
const payment = transaction.payment

switch (transaction.transactionState) {
case 'purchasing':
log.info(`Purchasing ${payment.productIdentifier}...`)
break

case 'purchased': {
log.info(`${payment.productIdentifier} purchased.`)

// Get the receipt url.
const receiptURL = inAppPurchase.getReceiptURL()

log.info(`Receipt URL: ${receiptURL}`)

// just assume that the receipt is valid, there is no reason to fake it.

// TODO try to load product information if not loaded yet, if not availible and failed return and let app try again later

// TODO send thank you device message over jsonrpc -> to active account

// Finish the transaction.
inAppPurchase.finishTransactionByDate(transaction.transactionDate)

break
}

case 'failed':
log.info(`Failed to purchase ${payment.productIdentifier}.`)

// Finish the transaction.
inAppPurchase.finishTransactionByDate(transaction.transactionDate)

break
case 'restored':
log.info(
`The purchase of ${payment.productIdentifier} has been restored.`
)

break
case 'deferred':
log.info(
`The purchase of ${payment.productIdentifier} has been deferred.`
)

break
default:
break
}
})
}
)

const PRODUCT_IDS = ['donation.small', 'default.monthly']

let loaded_products: Electron.Product[] | null = null

async function loadProducts(): Promise<Electron.Product[]> {
if (!loaded_products) {
// Retrieve and display the product descriptions.
const products = await inAppPurchase.getProducts(PRODUCT_IDS)

// Check the parameters.
if (!Array.isArray(products) || products.length <= 0) {
throw new Error('Unable to retrieve the product informations.')
}

products.forEach(product => {
log.info(
`The price of ${product.localizedTitle} is ${product.formattedPrice}.`
)
product.subscriptionPeriod
})

loaded_products = products
return products
} else {
return loaded_products
}
}

async function setupInAppPurchases(): Promise<
| { inAppDonationAvailible: false }
| { inAppDonationAvailible: true; paymentsAllowed: false }
| { inAppDonationAvailible: true; paymentsAllowed: true; error: string }
| {
inAppDonationAvailible: true
paymentsAllowed: true
}
> {
// TODO check if appstore build
if (platform() !== 'darwin') {
// if not mac or not appstore build
return {
inAppDonationAvailible: false,
}
}
if (!inAppPurchase.canMakePayments()) {
return {
inAppDonationAvailible: true,
paymentsAllowed: false,
}
} else {
return {
inAppDonationAvailible: true,
paymentsAllowed: true,
}
}
}

async function purchaseSingle(
productIdentifier: Electron.Product['productIdentifier']
) {
if (await inAppPurchase.purchaseProduct(productIdentifier, 1)) {
log.info('The payment has been added to the payment queue.')
} else {
log.info('The product is not valid:', { productIdentifier })
throw new Error('The product is not valid.')
}
}

// TODO:
// - get availible products
// - show thank you device message you when done

const THANK_YOU_MESSAGE = 'Thank you for donating $1!'
const THANK_YOU_MESSAGE_SUBSCRIPTION =
'Thank you for your monthly support of $1.\n\n Remember that you can cancel anytime on https://apps.apple.com/account/subscriptions'

const FAILED_MESSAGE = 'Your donation of $1 failed. :('



loadProducts().then(console.log)
setupInAppPurchases().then(console.log)
17 changes: 15 additions & 2 deletions src/renderer/components/dialogs/Settings-Donate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { contributeUrl, donationUrl } from '../../../shared/constants'
export function SettingsDonate({}: {}) {
const tx = window.static_translate

const MoneySection = false /* isMacAppstoreBuild */
const MoneySection = true /* isMacAppstoreBuild */
? DonateMacOSAppstore
: DonateMoney

Expand Down Expand Up @@ -51,5 +51,18 @@ function DonateMoney() {
}

function DonateMacOSAppstore() {
return <div>options</div>

// only one recuring donation option, because otherwise we'd need to track if the user is already subscribed
return (
<div>

<button
onClick={() =>
runtime.openLink('https://apps.apple.com/account/subscriptions')
}
>
Manage Recuring Donation
</button>
</div>
)
}

0 comments on commit 46af766

Please sign in to comment.